From c611903baf9590488e90d66976db8f3962e014fd Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Tue, 27 Aug 2019 15:52:39 +0300 Subject: [PATCH 01/25] Basic skeleton for blackbox script --- envs/monkey_zoo/blackbox/__init__.py | 0 envs/monkey_zoo/blackbox/requirements.txt | 2 ++ envs/monkey_zoo/blackbox/test_blackbox.py | 15 +++++++++++++++ 3 files changed, 17 insertions(+) create mode 100644 envs/monkey_zoo/blackbox/__init__.py create mode 100644 envs/monkey_zoo/blackbox/requirements.txt create mode 100644 envs/monkey_zoo/blackbox/test_blackbox.py diff --git a/envs/monkey_zoo/blackbox/__init__.py b/envs/monkey_zoo/blackbox/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/envs/monkey_zoo/blackbox/requirements.txt b/envs/monkey_zoo/blackbox/requirements.txt new file mode 100644 index 000000000..88d363f95 --- /dev/null +++ b/envs/monkey_zoo/blackbox/requirements.txt @@ -0,0 +1,2 @@ +pytest +unittest \ No newline at end of file diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py new file mode 100644 index 000000000..6cb0e5346 --- /dev/null +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -0,0 +1,15 @@ +import pytest +import unittest + + +class TestMonkeyBlackbox(unittest.TestCase): + @classmethod + def setUpClass(cls): + print("Setting up all GCP machines...") + + @classmethod + def tearDownClass(cls): + print("Killing all GCP machines...") + + def test_1_plus_1(self): + assert 1 + 1 == 2 From 0f5f01c4b14de5bccd9a60faaef64b642c69d8b7 Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Tue, 27 Aug 2019 16:23:09 +0300 Subject: [PATCH 02/25] Just some more skeleton code --- envs/monkey_zoo/blackbox/config.py | 2 ++ .../blackbox/island_configs/ssh.conf | 1 + envs/monkey_zoo/blackbox/test_blackbox.py | 19 ++++++++++++++++--- 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 envs/monkey_zoo/blackbox/config.py create mode 100644 envs/monkey_zoo/blackbox/island_configs/ssh.conf diff --git a/envs/monkey_zoo/blackbox/config.py b/envs/monkey_zoo/blackbox/config.py new file mode 100644 index 000000000..95efd9835 --- /dev/null +++ b/envs/monkey_zoo/blackbox/config.py @@ -0,0 +1,2 @@ +ISLAND_SERVER_ADDRESS = "1.2.3.4" +ISLAND_SERVER_URL_FORMAT = "https://{IP}/{resource}".format(IP=ISLAND_SERVER_ADDRESS) diff --git a/envs/monkey_zoo/blackbox/island_configs/ssh.conf b/envs/monkey_zoo/blackbox/island_configs/ssh.conf new file mode 100644 index 000000000..db656bbd5 --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_configs/ssh.conf @@ -0,0 +1 @@ +THIS IS AN EXAMPLE FILE. diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index 6cb0e5346..ed20ffd39 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -1,6 +1,9 @@ -import pytest import unittest +import requests + +from config import * + class TestMonkeyBlackbox(unittest.TestCase): @classmethod @@ -11,5 +14,15 @@ class TestMonkeyBlackbox(unittest.TestCase): def tearDownClass(cls): print("Killing all GCP machines...") - def test_1_plus_1(self): - assert 1 + 1 == 2 + def generic_blackbox_test_case(self, config_file_path, analyzers): + self.load_config_into_server(config_file_path) + self.run_local_monkey_on_island() + for analyzer in analyzers: + assert analyzer.analyze_test_results() + + def load_config_into_server(self, config_file_path): + print("uploading {} to {}".format(config_file_path, ISLAND_SERVER_ADDRESS)) + + def run_local_monkey_on_island(self): + print("Trying to run local monkey on {}".format(ISLAND_SERVER_ADDRESS)) + print(requests.get(ISLAND_SERVER_URL_FORMAT.format(resource="api"), verify=False).text) From a29408c07d04d99997c4871b4c65046e9fdadecf Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Tue, 27 Aug 2019 18:12:14 +0300 Subject: [PATCH 03/25] GCP handler implemented --- envs/monkey_zoo/blackbox/README.md | 4 +++ .../blackbox/gcp_machine_handlers.py | 34 +++++++++++++++++++ envs/monkey_zoo/blackbox/test_blackbox.py | 4 +++ 3 files changed, 42 insertions(+) create mode 100644 envs/monkey_zoo/blackbox/README.md create mode 100644 envs/monkey_zoo/blackbox/gcp_machine_handlers.py diff --git a/envs/monkey_zoo/blackbox/README.md b/envs/monkey_zoo/blackbox/README.md new file mode 100644 index 000000000..0c66ba58a --- /dev/null +++ b/envs/monkey_zoo/blackbox/README.md @@ -0,0 +1,4 @@ +# Automatic blackbox tests +### Prerequisites +1. Download google sdk: https://cloud.google.com/sdk/docs/ +2. Download service account key GCP console -> IAM -> service accounts(you can use the same key used to authenticate terraform scripts) diff --git a/envs/monkey_zoo/blackbox/gcp_machine_handlers.py b/envs/monkey_zoo/blackbox/gcp_machine_handlers.py new file mode 100644 index 000000000..aae0c34b4 --- /dev/null +++ b/envs/monkey_zoo/blackbox/gcp_machine_handlers.py @@ -0,0 +1,34 @@ +import subprocess + + +class GCPHandler(object): + + AUTHENTICATION_COMMAND = "gcloud auth activate-service-account --key-file=%s" + MACHINE_STARTING_COMMAND = "gcloud compute instances start %s --zone=%s" + MACHINE_STOPPING_COMMAND = "gcloud compute instances stop %s --zone=%s" + + def __init__(self, key_path="../gcp_keys/gcp_key.json", zone="europe-west3-a"): + self.zone = zone + try: + subprocess.call(GCPHandler.get_auth_command(key_path), shell=True) + print("GCP Handler initialized successfully") + except Exception as e: + print("GCP Handler failed to initialize: %s." % e) + + def start_machines(self, machine_list): + try: + subprocess.call((GCPHandler.MACHINE_STARTING_COMMAND % (machine_list, self.zone)), shell=True) + print("GCP machines successfully started.") + except Exception as e: + print("GCP Handler failed to start GCP machines: %s" % e) + + def stop_machines(self, machine_list): + try: + subprocess.call((GCPHandler.MACHINE_STOPPING_COMMAND % (machine_list, self.zone)), shell=True) + print("GCP machines stopped successfully.") + except Exception as e: + print("GCP Handler failed to stop network machines: %s" % e) + + @staticmethod + def get_auth_command(key_path): + return GCPHandler.AUTHENTICATION_COMMAND % key_path diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index ed20ffd39..0ed1e2a37 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -1,4 +1,5 @@ import unittest +from .gcp_machine_handlers import GCPHandler import requests @@ -6,12 +7,15 @@ from config import * class TestMonkeyBlackbox(unittest.TestCase): + @classmethod def setUpClass(cls): + GCPHandler().start_machines("elastic-4") print("Setting up all GCP machines...") @classmethod def tearDownClass(cls): + GCPHandler().stop_machines("elastic-4") print("Killing all GCP machines...") def generic_blackbox_test_case(self, config_file_path, analyzers): From 45fa7570ef700ea17a1af1c727f98ca6657873d3 Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Wed, 28 Aug 2019 14:26:39 +0300 Subject: [PATCH 04/25] Add monkey zoo gitignore so we don't commit keys be accident --- envs/monkey_zoo/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 envs/monkey_zoo/.gitignore diff --git a/envs/monkey_zoo/.gitignore b/envs/monkey_zoo/.gitignore new file mode 100644 index 000000000..5fda323da --- /dev/null +++ b/envs/monkey_zoo/.gitignore @@ -0,0 +1 @@ +gcp_keys/ From 11a157889341d9d7be1595cf4f40f3f75c073eea Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Wed, 28 Aug 2019 14:56:35 +0300 Subject: [PATCH 05/25] Added setting project to GCPHandler --- envs/monkey_zoo/blackbox/config.py | 2 +- .../blackbox/gcp_machine_handlers.py | 12 ++++++- envs/monkey_zoo/blackbox/test_blackbox.py | 32 +++++++++++++------ 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/envs/monkey_zoo/blackbox/config.py b/envs/monkey_zoo/blackbox/config.py index 95efd9835..2a38498fd 100644 --- a/envs/monkey_zoo/blackbox/config.py +++ b/envs/monkey_zoo/blackbox/config.py @@ -1,2 +1,2 @@ ISLAND_SERVER_ADDRESS = "1.2.3.4" -ISLAND_SERVER_URL_FORMAT = "https://{IP}/{resource}".format(IP=ISLAND_SERVER_ADDRESS) +ISLAND_SERVER_URL = "https://{IP}/".format(IP=ISLAND_SERVER_ADDRESS) diff --git a/envs/monkey_zoo/blackbox/gcp_machine_handlers.py b/envs/monkey_zoo/blackbox/gcp_machine_handlers.py index aae0c34b4..4937191ed 100644 --- a/envs/monkey_zoo/blackbox/gcp_machine_handlers.py +++ b/envs/monkey_zoo/blackbox/gcp_machine_handlers.py @@ -4,13 +4,19 @@ import subprocess class GCPHandler(object): AUTHENTICATION_COMMAND = "gcloud auth activate-service-account --key-file=%s" + SET_PROPERTY_PROJECT = "gcloud config set project %s" MACHINE_STARTING_COMMAND = "gcloud compute instances start %s --zone=%s" MACHINE_STOPPING_COMMAND = "gcloud compute instances stop %s --zone=%s" - def __init__(self, key_path="../gcp_keys/gcp_key.json", zone="europe-west3-a"): + def __init__(self, key_path="../gcp_keys/gcp_key.json", zone="europe-west3-a", project_id="guardicore-22050661"): self.zone = zone try: + # pass the key file to gcp subprocess.call(GCPHandler.get_auth_command(key_path), shell=True) + print("GCP Handler passed key") + # set project + subprocess.call(GCPHandler.get_set_project_command(project_id), shell=True) + print("GCP Handler set project") print("GCP Handler initialized successfully") except Exception as e: print("GCP Handler failed to initialize: %s." % e) @@ -32,3 +38,7 @@ class GCPHandler(object): @staticmethod def get_auth_command(key_path): return GCPHandler.AUTHENTICATION_COMMAND % key_path + + @staticmethod + def get_set_project_command(project): + return GCPHandler.SET_PROPERTY_PROJECT % project diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index 0ed1e2a37..a9afd5244 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -1,3 +1,4 @@ +import os import unittest from .gcp_machine_handlers import GCPHandler @@ -6,6 +7,13 @@ import requests from config import * +def generic_blackbox_test_case(config_file_path, analyzers): + load_config_into_server(config_file_path) + run_local_monkey_on_island() + for analyzer in analyzers: + assert analyzer.analyze_test_results() + + class TestMonkeyBlackbox(unittest.TestCase): @classmethod @@ -18,15 +26,19 @@ class TestMonkeyBlackbox(unittest.TestCase): GCPHandler().stop_machines("elastic-4") print("Killing all GCP machines...") - def generic_blackbox_test_case(self, config_file_path, analyzers): - self.load_config_into_server(config_file_path) - self.run_local_monkey_on_island() - for analyzer in analyzers: - assert analyzer.analyze_test_results() + def test_ssh_exec(self): + conf_file_name = "ssh.conf" + generic_blackbox_test_case(get_conf_file_path(conf_file_name), []) - def load_config_into_server(self, config_file_path): - print("uploading {} to {}".format(config_file_path, ISLAND_SERVER_ADDRESS)) - def run_local_monkey_on_island(self): - print("Trying to run local monkey on {}".format(ISLAND_SERVER_ADDRESS)) - print(requests.get(ISLAND_SERVER_URL_FORMAT.format(resource="api"), verify=False).text) +def run_local_monkey_on_island(): + print("Trying to run local monkey on {}".format(ISLAND_SERVER_ADDRESS)) + print(ISLAND_SERVER_URL + "api") + + +def load_config_into_server(config_file_path): + print("uploading {} to {}".format(config_file_path, ISLAND_SERVER_ADDRESS)) + + +def get_conf_file_path(conf_file_name): + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "island_configs", conf_file_name) From 0a512ac9eb6826e31b6b831b7a4a22996206de58 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Wed, 28 Aug 2019 18:20:24 +0300 Subject: [PATCH 06/25] temp ssh conf removed --- envs/monkey_zoo/blackbox/island_configs/ssh.conf | 1 - 1 file changed, 1 deletion(-) delete mode 100644 envs/monkey_zoo/blackbox/island_configs/ssh.conf diff --git a/envs/monkey_zoo/blackbox/island_configs/ssh.conf b/envs/monkey_zoo/blackbox/island_configs/ssh.conf deleted file mode 100644 index db656bbd5..000000000 --- a/envs/monkey_zoo/blackbox/island_configs/ssh.conf +++ /dev/null @@ -1 +0,0 @@ -THIS IS AN EXAMPLE FILE. From cd81588f090c21e40277fa6873c15b4c45edc276 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Wed, 28 Aug 2019 18:21:14 +0300 Subject: [PATCH 07/25] island configurations for tests added --- .../blackbox/island_configs/ELASTIC.conf | 184 ++++++++++++++++ .../blackbox/island_configs/HADOOP.conf | 195 +++++++++++++++++ .../blackbox/island_configs/MSSQL.conf | 183 ++++++++++++++++ .../blackbox/island_configs/SHELLSHOCK.conf | 183 ++++++++++++++++ .../blackbox/island_configs/SMB_MIMIKATZ.conf | 185 ++++++++++++++++ .../blackbox/island_configs/SSH.conf | 205 ++++++++++++++++++ .../blackbox/island_configs/STRUTS2.conf | 193 +++++++++++++++++ .../blackbox/island_configs/TUNNELING.conf | 194 +++++++++++++++++ .../blackbox/island_configs/WEBLOGIC.conf | 184 ++++++++++++++++ .../blackbox/island_configs/WMI_MIMIKATZ.conf | 192 ++++++++++++++++ 10 files changed, 1898 insertions(+) create mode 100644 envs/monkey_zoo/blackbox/island_configs/ELASTIC.conf create mode 100644 envs/monkey_zoo/blackbox/island_configs/HADOOP.conf create mode 100644 envs/monkey_zoo/blackbox/island_configs/MSSQL.conf create mode 100644 envs/monkey_zoo/blackbox/island_configs/SHELLSHOCK.conf create mode 100644 envs/monkey_zoo/blackbox/island_configs/SMB_MIMIKATZ.conf create mode 100644 envs/monkey_zoo/blackbox/island_configs/SSH.conf create mode 100644 envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf create mode 100644 envs/monkey_zoo/blackbox/island_configs/TUNNELING.conf create mode 100644 envs/monkey_zoo/blackbox/island_configs/WEBLOGIC.conf create mode 100644 envs/monkey_zoo/blackbox/island_configs/WMI_MIMIKATZ.conf diff --git a/envs/monkey_zoo/blackbox/island_configs/ELASTIC.conf b/envs/monkey_zoo/blackbox/island_configs/ELASTIC.conf new file mode 100644 index 000000000..4bf0af990 --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_configs/ELASTIC.conf @@ -0,0 +1,184 @@ +{ + "basic": { + "credentials": { + "exploit_password_list": [ + "Password1!", + "1234", + "password", + "12345678" + ], + "exploit_user_list": [ + "Administrator", + "root", + "user" + ] + }, + "general": { + "should_exploit": true + } + }, + "basic_network": { + "general": { + "blocked_ips": [], + "depth": 2, + "local_network_scan": true, + "subnet_scan_list": [ + "10.2.2.4", + "10.2.2.5" + ] + }, + "network_analysis": { + "inaccessible_subnets": [] + } + }, + "cnc": { + "servers": { + "command_servers": [ + "10.2.2.251:5000" + ], + "current_server": "10.2.2.251:5000", + "internet_services": [ + "monkey.guardicore.com", + "www.google.com" + ] + } + }, + "exploits": { + "general": { + "exploiter_classes": [ + "ElasticGroovyExploiter" + ], + "skip_exploit_if_file_exist": false + }, + "ms08_067": { + "ms08_067_exploit_attempts": 5, + "remote_user_pass": "Password1!", + "user_to_add": "Monkey_IUSER_SUPPORT" + }, + "rdp_grinder": { + "rdp_use_vbs_download": true + }, + "sambacry": { + "sambacry_folder_paths_to_guess": [ + "/", + "/mnt", + "/tmp", + "/storage", + "/export", + "/share", + "/shares", + "/home" + ], + "sambacry_shares_not_to_check": [ + "IPC$", + "print$" + ], + "sambacry_trigger_timeout": 5 + }, + "smb_service": { + "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey" + } + }, + "internal": { + "classes": { + "finger_classes": [ + "SMBFinger", + "SSHFinger", + "PingScanner", + "HTTPFinger", + "MySQLFinger", + "MSSQLFinger", + "ElasticFinger" + ] + }, + "dropper": { + "dropper_date_reference_path_linux": "/bin/sh", + "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", + "dropper_set_date": true, + "dropper_target_path_linux": "/tmp/monkey", + "dropper_target_path_win_32": "C:\\Windows\\temp\\monkey32.exe", + "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", + "dropper_try_move_first": true + }, + "exploits": { + "exploit_lm_hash_list": [], + "exploit_ntlm_hash_list": [], + "exploit_ssh_keys": [] + }, + "general": { + "keep_tunnel_open_time": 60, + "monkey_dir_name": "monkey_dir", + "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" + }, + "kill_file": { + "kill_file_path_linux": "/var/run/monkey.not", + "kill_file_path_windows": "%windir%\\monkey.not" + }, + "logging": { + "dropper_log_path_linux": "/tmp/user-1562", + "dropper_log_path_windows": "%temp%\\~df1562.tmp", + "monkey_log_path_linux": "/tmp/user-1563", + "monkey_log_path_windows": "%temp%\\~df1563.tmp", + "send_log_to_server": true + } + }, + "monkey": { + "behaviour": { + "PBA_linux_filename": "", + "PBA_windows_filename": "", + "custom_PBA_linux_cmd": "", + "custom_PBA_windows_cmd": "", + "self_delete_in_cleanup": true, + "serialize_config": false, + "use_file_logging": true + }, + "general": { + "alive": true, + "post_breach_actions": [] + }, + "life_cycle": { + "max_iterations": 1, + "retry_failed_explotation": true, + "timeout_between_iterations": 100, + "victims_max_exploit": 7, + "victims_max_find": 30 + }, + "system_info": { + "collect_system_info": true, + "extract_azure_creds": true, + "should_use_mimikatz": true + } + }, + "network": { + "ping_scanner": { + "ping_scan_timeout": 1000 + }, + "tcp_scanner": { + "HTTP_PORTS": [ + 80, + 8080, + 443, + 8008, + 7001 + ], + "tcp_scan_get_banner": true, + "tcp_scan_interval": 0, + "tcp_scan_timeout": 3000, + "tcp_target_ports": [ + 22, + 2222, + 445, + 135, + 3389, + 80, + 8080, + 443, + 8008, + 3306, + 9200, + 7001 + ] + } + } +} \ No newline at end of file diff --git a/envs/monkey_zoo/blackbox/island_configs/HADOOP.conf b/envs/monkey_zoo/blackbox/island_configs/HADOOP.conf new file mode 100644 index 000000000..f61afc9ae --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_configs/HADOOP.conf @@ -0,0 +1,195 @@ +{ + "basic": { + "credentials": { + "exploit_password_list": [ + "Password1!", + "1234", + "password", + "12345678" + ], + "exploit_user_list": [ + "Administrator", + "root", + "user" + ] + }, + "general": { + "should_exploit": true + } + }, + "basic_network": { + "general": { + "blocked_ips": [], + "depth": 2, + "local_network_scan": false, + "subnet_scan_list": [ + "10.2.2.3", + "10.2.2.10" + ] + }, + "network_analysis": { + "inaccessible_subnets": [] + } + }, + "cnc": { + "servers": { + "command_servers": [ + "10.2.2.251:5000" + ], + "current_server": "10.2.2.251:5000", + "internet_services": [ + "monkey.guardicore.com", + "www.google.com" + ] + } + }, + "exploits": { + "general": { + "exploiter_classes": [ + "SmbExploiter", + "WmiExploiter", + "SSHExploiter", + "ShellShockExploiter", + "SambaCryExploiter", + "ElasticGroovyExploiter", + "Struts2Exploiter", + "WebLogicExploiter", + "HadoopExploiter", + "VSFTPDExploiter" + ], + "skip_exploit_if_file_exist": false + }, + "ms08_067": { + "ms08_067_exploit_attempts": 5, + "remote_user_pass": "Password1!", + "user_to_add": "Monkey_IUSER_SUPPORT" + }, + "rdp_grinder": { + "rdp_use_vbs_download": true + }, + "sambacry": { + "sambacry_folder_paths_to_guess": [ + "/", + "/mnt", + "/tmp", + "/storage", + "/export", + "/share", + "/shares", + "/home" + ], + "sambacry_shares_not_to_check": [ + "IPC$", + "print$" + ], + "sambacry_trigger_timeout": 5 + }, + "smb_service": { + "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey" + } + }, + "internal": { + "classes": { + "finger_classes": [ + "SMBFinger", + "SSHFinger", + "PingScanner", + "HTTPFinger", + "MySQLFinger", + "MSSQLFinger", + "ElasticFinger" + ] + }, + "dropper": { + "dropper_date_reference_path_linux": "/bin/sh", + "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", + "dropper_set_date": true, + "dropper_target_path_linux": "/tmp/monkey", + "dropper_target_path_win_32": "C:\\Windows\\temp\\monkey32.exe", + "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", + "dropper_try_move_first": true + }, + "exploits": { + "exploit_lm_hash_list": [], + "exploit_ntlm_hash_list": [ + "e1c0dc690821c13b10a41dccfc72e43a" + ], + "exploit_ssh_keys": [] + }, + "general": { + "keep_tunnel_open_time": 60, + "monkey_dir_name": "monkey_dir", + "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" + }, + "kill_file": { + "kill_file_path_linux": "/var/run/monkey.not", + "kill_file_path_windows": "%windir%\\monkey.not" + }, + "logging": { + "dropper_log_path_linux": "/tmp/user-1562", + "dropper_log_path_windows": "%temp%\\~df1562.tmp", + "monkey_log_path_linux": "/tmp/user-1563", + "monkey_log_path_windows": "%temp%\\~df1563.tmp", + "send_log_to_server": true + } + }, + "monkey": { + "behaviour": { + "PBA_linux_filename": "", + "PBA_windows_filename": "", + "custom_PBA_linux_cmd": "", + "custom_PBA_windows_cmd": "", + "self_delete_in_cleanup": true, + "serialize_config": false, + "use_file_logging": true + }, + "general": { + "alive": true, + "post_breach_actions": [] + }, + "life_cycle": { + "max_iterations": 1, + "retry_failed_explotation": true, + "timeout_between_iterations": 100, + "victims_max_exploit": 7, + "victims_max_find": 30 + }, + "system_info": { + "collect_system_info": true, + "extract_azure_creds": true, + "should_use_mimikatz": true + } + }, + "network": { + "ping_scanner": { + "ping_scan_timeout": 1000 + }, + "tcp_scanner": { + "HTTP_PORTS": [ + 80, + 8080, + 443, + 8008, + 7001 + ], + "tcp_scan_get_banner": true, + "tcp_scan_interval": 0, + "tcp_scan_timeout": 3000, + "tcp_target_ports": [ + 22, + 2222, + 445, + 135, + 3389, + 80, + 8080, + 443, + 8008, + 3306, + 9200, + 7001 + ] + } + } +} \ No newline at end of file diff --git a/envs/monkey_zoo/blackbox/island_configs/MSSQL.conf b/envs/monkey_zoo/blackbox/island_configs/MSSQL.conf new file mode 100644 index 000000000..111cd304f --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_configs/MSSQL.conf @@ -0,0 +1,183 @@ +{ + "basic": { + "credentials": { + "exploit_password_list": [ + "Password1!", + "Xk8VDTsC", + "password", + "12345678" + ], + "exploit_user_list": [ + "Administrator", + "m0nk3y", + "user" + ] + }, + "general": { + "should_exploit": true + } + }, + "basic_network": { + "general": { + "blocked_ips": [], + "depth": 2, + "local_network_scan": false, + "subnet_scan_list": [ + "10.2.2.16" + ] + }, + "network_analysis": { + "inaccessible_subnets": [] + } + }, + "cnc": { + "servers": { + "command_servers": [ + "10.2.2.251:5000" + ], + "current_server": "10.2.2.251:5000", + "internet_services": [ + "monkey.guardicore.com", + "www.google.com" + ] + } + }, + "exploits": { + "general": { + "exploiter_classes": [ + "MSSQLExploiter" + ], + "skip_exploit_if_file_exist": false + }, + "ms08_067": { + "ms08_067_exploit_attempts": 5, + "remote_user_pass": "Password1!", + "user_to_add": "Monkey_IUSER_SUPPORT" + }, + "rdp_grinder": { + "rdp_use_vbs_download": true + }, + "sambacry": { + "sambacry_folder_paths_to_guess": [ + "/", + "/mnt", + "/tmp", + "/storage", + "/export", + "/share", + "/shares", + "/home" + ], + "sambacry_shares_not_to_check": [ + "IPC$", + "print$" + ], + "sambacry_trigger_timeout": 5 + }, + "smb_service": { + "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey" + } + }, + "internal": { + "classes": { + "finger_classes": [ + "SMBFinger", + "SSHFinger", + "PingScanner", + "HTTPFinger", + "MySQLFinger", + "MSSQLFinger", + "ElasticFinger" + ] + }, + "dropper": { + "dropper_date_reference_path_linux": "/bin/sh", + "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", + "dropper_set_date": true, + "dropper_target_path_linux": "/tmp/monkey", + "dropper_target_path_win_32": "C:\\Windows\\temp\\monkey32.exe", + "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", + "dropper_try_move_first": true + }, + "exploits": { + "exploit_lm_hash_list": [], + "exploit_ntlm_hash_list": [], + "exploit_ssh_keys": [] + }, + "general": { + "keep_tunnel_open_time": 60, + "monkey_dir_name": "monkey_dir", + "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" + }, + "kill_file": { + "kill_file_path_linux": "/var/run/monkey.not", + "kill_file_path_windows": "%windir%\\monkey.not" + }, + "logging": { + "dropper_log_path_linux": "/tmp/user-1562", + "dropper_log_path_windows": "%temp%\\~df1562.tmp", + "monkey_log_path_linux": "/tmp/user-1563", + "monkey_log_path_windows": "%temp%\\~df1563.tmp", + "send_log_to_server": true + } + }, + "monkey": { + "behaviour": { + "PBA_linux_filename": "", + "PBA_windows_filename": "", + "custom_PBA_linux_cmd": "", + "custom_PBA_windows_cmd": "", + "self_delete_in_cleanup": true, + "serialize_config": false, + "use_file_logging": true + }, + "general": { + "alive": true, + "post_breach_actions": [] + }, + "life_cycle": { + "max_iterations": 1, + "retry_failed_explotation": true, + "timeout_between_iterations": 100, + "victims_max_exploit": 7, + "victims_max_find": 30 + }, + "system_info": { + "collect_system_info": true, + "extract_azure_creds": true, + "should_use_mimikatz": true + } + }, + "network": { + "ping_scanner": { + "ping_scan_timeout": 1000 + }, + "tcp_scanner": { + "HTTP_PORTS": [ + 80, + 8080, + 443, + 8008, + 7001 + ], + "tcp_scan_get_banner": true, + "tcp_scan_interval": 0, + "tcp_scan_timeout": 3000, + "tcp_target_ports": [ + 22, + 2222, + 445, + 135, + 3389, + 80, + 8080, + 443, + 8008, + 3306, + 9200, + 7001 + ] + } + } +} \ No newline at end of file diff --git a/envs/monkey_zoo/blackbox/island_configs/SHELLSHOCK.conf b/envs/monkey_zoo/blackbox/island_configs/SHELLSHOCK.conf new file mode 100644 index 000000000..0ca343ae0 --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_configs/SHELLSHOCK.conf @@ -0,0 +1,183 @@ +{ + "basic": { + "credentials": { + "exploit_password_list": [ + "Password1!", + "1234", + "password", + "12345678" + ], + "exploit_user_list": [ + "Administrator", + "root", + "user" + ] + }, + "general": { + "should_exploit": true + } + }, + "basic_network": { + "general": { + "blocked_ips": [], + "depth": 2, + "local_network_scan": false, + "subnet_scan_list": [ + "10.2.2.38" + ] + }, + "network_analysis": { + "inaccessible_subnets": [] + } + }, + "cnc": { + "servers": { + "command_servers": [ + "10.2.2.251:5000" + ], + "current_server": "10.2.2.251:5000", + "internet_services": [ + "monkey.guardicore.com", + "www.google.com" + ] + } + }, + "exploits": { + "general": { + "exploiter_classes": [ + "ShellShockExploiter" + ], + "skip_exploit_if_file_exist": false + }, + "ms08_067": { + "ms08_067_exploit_attempts": 5, + "remote_user_pass": "Password1!", + "user_to_add": "Monkey_IUSER_SUPPORT" + }, + "rdp_grinder": { + "rdp_use_vbs_download": true + }, + "sambacry": { + "sambacry_folder_paths_to_guess": [ + "/", + "/mnt", + "/tmp", + "/storage", + "/export", + "/share", + "/shares", + "/home" + ], + "sambacry_shares_not_to_check": [ + "IPC$", + "print$" + ], + "sambacry_trigger_timeout": 5 + }, + "smb_service": { + "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey" + } + }, + "internal": { + "classes": { + "finger_classes": [ + "SMBFinger", + "SSHFinger", + "PingScanner", + "HTTPFinger", + "MySQLFinger", + "MSSQLFinger", + "ElasticFinger" + ] + }, + "dropper": { + "dropper_date_reference_path_linux": "/bin/sh", + "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", + "dropper_set_date": true, + "dropper_target_path_linux": "/tmp/monkey", + "dropper_target_path_win_32": "C:\\Windows\\temp\\monkey32.exe", + "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", + "dropper_try_move_first": true + }, + "exploits": { + "exploit_lm_hash_list": [], + "exploit_ntlm_hash_list": [], + "exploit_ssh_keys": [] + }, + "general": { + "keep_tunnel_open_time": 60, + "monkey_dir_name": "monkey_dir", + "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" + }, + "kill_file": { + "kill_file_path_linux": "/var/run/monkey.not", + "kill_file_path_windows": "%windir%\\monkey.not" + }, + "logging": { + "dropper_log_path_linux": "/tmp/user-1562", + "dropper_log_path_windows": "%temp%\\~df1562.tmp", + "monkey_log_path_linux": "/tmp/user-1563", + "monkey_log_path_windows": "%temp%\\~df1563.tmp", + "send_log_to_server": true + } + }, + "monkey": { + "behaviour": { + "PBA_linux_filename": "", + "PBA_windows_filename": "", + "custom_PBA_linux_cmd": "", + "custom_PBA_windows_cmd": "", + "self_delete_in_cleanup": true, + "serialize_config": false, + "use_file_logging": true + }, + "general": { + "alive": true, + "post_breach_actions": [] + }, + "life_cycle": { + "max_iterations": 1, + "retry_failed_explotation": true, + "timeout_between_iterations": 100, + "victims_max_exploit": 7, + "victims_max_find": 30 + }, + "system_info": { + "collect_system_info": true, + "extract_azure_creds": true, + "should_use_mimikatz": true + } + }, + "network": { + "ping_scanner": { + "ping_scan_timeout": 1000 + }, + "tcp_scanner": { + "HTTP_PORTS": [ + 80, + 8080, + 443, + 8008, + 7001 + ], + "tcp_scan_get_banner": true, + "tcp_scan_interval": 0, + "tcp_scan_timeout": 3000, + "tcp_target_ports": [ + 22, + 2222, + 445, + 135, + 3389, + 80, + 8080, + 443, + 8008, + 3306, + 9200, + 7001 + ] + } + } +} \ No newline at end of file diff --git a/envs/monkey_zoo/blackbox/island_configs/SMB_MIMIKATZ.conf b/envs/monkey_zoo/blackbox/island_configs/SMB_MIMIKATZ.conf new file mode 100644 index 000000000..bfccc4d62 --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_configs/SMB_MIMIKATZ.conf @@ -0,0 +1,185 @@ +{ + "basic": { + "credentials": { + "exploit_password_list": [ + "Password1!", + "Ivrrw5zEzs" + ], + "exploit_user_list": [ + "Administrator", + "m0nk3y", + "user" + ] + }, + "general": { + "should_exploit": true + } + }, + "basic_network": { + "general": { + "blocked_ips": [], + "depth": 2, + "local_network_scan": false, + "subnet_scan_list": [ + "10.2.2.44", + "10.2.2.15" + ] + }, + "network_analysis": { + "inaccessible_subnets": [] + } + }, + "cnc": { + "servers": { + "command_servers": [ + "10.2.2.251:5000" + ], + "current_server": "10.2.2.251:5000", + "internet_services": [ + "monkey.guardicore.com", + "www.google.com" + ] + } + }, + "exploits": { + "general": { + "exploiter_classes": [ + "SmbExploiter" + ], + "skip_exploit_if_file_exist": false + }, + "ms08_067": { + "ms08_067_exploit_attempts": 5, + "remote_user_pass": "Password1!", + "user_to_add": "Monkey_IUSER_SUPPORT" + }, + "rdp_grinder": { + "rdp_use_vbs_download": true + }, + "sambacry": { + "sambacry_folder_paths_to_guess": [ + "/", + "/mnt", + "/tmp", + "/storage", + "/export", + "/share", + "/shares", + "/home" + ], + "sambacry_shares_not_to_check": [ + "IPC$", + "print$" + ], + "sambacry_trigger_timeout": 5 + }, + "smb_service": { + "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey" + } + }, + "internal": { + "classes": { + "finger_classes": [ + "SMBFinger", + "SSHFinger", + "PingScanner", + "HTTPFinger", + "MySQLFinger", + "MSSQLFinger", + "ElasticFinger" + ] + }, + "dropper": { + "dropper_date_reference_path_linux": "/bin/sh", + "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", + "dropper_set_date": true, + "dropper_target_path_linux": "/tmp/monkey", + "dropper_target_path_win_32": "C:\\Windows\\temp\\monkey32.exe", + "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", + "dropper_try_move_first": true + }, + "exploits": { + "exploit_lm_hash_list": [], + "exploit_ntlm_hash_list": [ + "5da0889ea2081aa79f6852294cba4a5e", + "5da0889ea2081aa79f6852294cba4a5e" + ], + "exploit_ssh_keys": [] + }, + "general": { + "keep_tunnel_open_time": 60, + "monkey_dir_name": "monkey_dir", + "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" + }, + "kill_file": { + "kill_file_path_linux": "/var/run/monkey.not", + "kill_file_path_windows": "%windir%\\monkey.not" + }, + "logging": { + "dropper_log_path_linux": "/tmp/user-1562", + "dropper_log_path_windows": "%temp%\\~df1562.tmp", + "monkey_log_path_linux": "/tmp/user-1563", + "monkey_log_path_windows": "%temp%\\~df1563.tmp", + "send_log_to_server": true + } + }, + "monkey": { + "behaviour": { + "PBA_linux_filename": "", + "PBA_windows_filename": "", + "custom_PBA_linux_cmd": "", + "custom_PBA_windows_cmd": "", + "self_delete_in_cleanup": true, + "serialize_config": false, + "use_file_logging": true + }, + "general": { + "alive": true, + "post_breach_actions": [] + }, + "life_cycle": { + "max_iterations": 2, + "retry_failed_explotation": true, + "timeout_between_iterations": 100, + "victims_max_exploit": 7, + "victims_max_find": 30 + }, + "system_info": { + "collect_system_info": true, + "extract_azure_creds": true, + "should_use_mimikatz": true + } + }, + "network": { + "ping_scanner": { + "ping_scan_timeout": 1000 + }, + "tcp_scanner": { + "HTTP_PORTS": [ + 80, + 8080, + 443, + 8008, + 7001 + ], + "tcp_scan_get_banner": true, + "tcp_scan_interval": 0, + "tcp_scan_timeout": 3000, + "tcp_target_ports": [ + 22, + 2222, + 445, + 135, + 3389, + 80, + 8080, + 443, + 8008, + 3306, + 9200, + 7001 + ] + } + } +} \ No newline at end of file diff --git a/envs/monkey_zoo/blackbox/island_configs/SSH.conf b/envs/monkey_zoo/blackbox/island_configs/SSH.conf new file mode 100644 index 000000000..da4325f85 --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_configs/SSH.conf @@ -0,0 +1,205 @@ +{ + "basic": { + "credentials": { + "exploit_password_list": [ + "Password1!", + "12345678", + "^NgDvY59~8" + ], + "exploit_user_list": [ + "Administrator", + "m0nk3y", + "user" + ] + }, + "general": { + "should_exploit": true + } + }, + "basic_network": { + "general": { + "blocked_ips": [], + "depth": 2, + "local_network_scan": false, + "subnet_scan_list": [ + "10.2.2.41", + "10.2.2.42" + ] + }, + "network_analysis": { + "inaccessible_subnets": [] + } + }, + "cnc": { + "servers": { + "command_servers": [ + "10.2.2.251:5000" + ], + "current_server": "10.2.2.251:5000", + "internet_services": [ + "monkey.guardicore.com", + "www.google.com" + ] + } + }, + "exploits": { + "general": { + "exploiter_classes": [ + "SmbExploiter", + "WmiExploiter", + "SSHExploiter", + "ShellShockExploiter", + "SambaCryExploiter", + "ElasticGroovyExploiter", + "Struts2Exploiter", + "WebLogicExploiter", + "HadoopExploiter", + "VSFTPDExploiter" + ], + "skip_exploit_if_file_exist": false + }, + "ms08_067": { + "ms08_067_exploit_attempts": 5, + "remote_user_pass": "Password1!", + "user_to_add": "Monkey_IUSER_SUPPORT" + }, + "rdp_grinder": { + "rdp_use_vbs_download": true + }, + "sambacry": { + "sambacry_folder_paths_to_guess": [ + "/", + "/mnt", + "/tmp", + "/storage", + "/export", + "/share", + "/shares", + "/home" + ], + "sambacry_shares_not_to_check": [ + "IPC$", + "print$" + ], + "sambacry_trigger_timeout": 5 + }, + "smb_service": { + "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey" + } + }, + "internal": { + "classes": { + "finger_classes": [ + "SMBFinger", + "SSHFinger", + "PingScanner", + "HTTPFinger", + "MySQLFinger", + "MSSQLFinger", + "ElasticFinger" + ] + }, + "dropper": { + "dropper_date_reference_path_linux": "/bin/sh", + "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", + "dropper_set_date": true, + "dropper_target_path_linux": "/tmp/monkey", + "dropper_target_path_win_32": "C:\\Windows\\temp\\monkey32.exe", + "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", + "dropper_try_move_first": true + }, + "exploits": { + "exploit_lm_hash_list": [], + "exploit_ntlm_hash_list": [], + "exploit_ssh_keys": [ + { + "ip": "10.2.2.41", + "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAyH0k1LOILDTVli5NlqcvRdoRc2aMn5I5ZhJsnBNuzB28D6Fd\nAEbjDn/v+dPK58L4WGoGMpHqk47mNDgdTIkfP5BBgbuQpBUmrsCZn8QVRpqZ3ESC\nXsnMrOjrYRqTelquGWR9xJvIJwNz3UbME2c8SYOPc3tHsINyn8Tt2ssA8L9KjcTe\n6CzNpbCNbZ6Q3o7/isYP79ogiFY+VHK3rtBY17aG9bDx5vce8RoIr463u/+a+jYX\nPuzZgndTtO3EPwq4Ti1pydpuJo9PYh1iY6RP3XPMYNwpoKToYzyESeqqwolmz+nh\nEh/rQtuwwW7043IM+62w9UPkHWv28pqDZxBxhwIDAQABAoIBAGA1/ei8xwo/yIer\nbLxxOnRQ87LncXBaIYVkLg6wHKmDU25Ex3aMjgW1S5oeEu8pVzhGmPbHo0RwfPRu\nQVErNH2yYl05f23eYJPYBWDwHi2ln1Re5BlMyhXoKJyOvlsnDQlOejRRdbmTJJT5\nlpFxJzM4GS0X6g1A507YmDQ42xisOkmL/Wsv/t9/GiE9P6h0I1bNmXzSy8sDZwea\nNDe09U+rfuIkh2tO+nEzWs13AG3CxV9YlK4vMK7A0KiWF8LPvrbBegEm5VG+qrJ2\nsxoDkCBc5DV6QRyLU1SIyDIRIR2J0gTgfLDSbqNp0qm+Zby2o3V/q26bvrWWwP9a\nU/W2vJECgYEA5jK52pUMmriCiWNgQOiyOGx5OfHo6gRomiiiALivaMhNN3mm8CFI\nuIXMjU1V0BoHXCW8ciMOAeXl72rX/XVC+/E3GJQFCtBHJQ6tPNOOnWcxR/Ldwvxd\nsBz8Wx50MlxvbrxqtzTn+VmVnExKskwsZGI/GDPotPo7QKcBJUsGfhsCgYEA3vXx\ncyG805RsJH/J54cg+cHW5xDn6YNuHwbVdB4FWfi184oDDxtPT84XF1JA3dN3gwJF\nSfO1kNwpNK0C58evJA+6rZfUps/HOcQqFPvzCUhkLeZD5QgaOTQZBKndXYgeXkJD\ntpN+kjhCdxWN40N6FAMtLUYTbaQdTUHSBuXzoQUCgYEAgwXgTw+DCxV2ByjvAkLw\nHblwDpEoVvqHZyc1fl+gR22qtaaiZA8tywks8khQTZBjHAnGhth5Ao+OHoWbxoHV\nzHzxNSYa8Jq3w9nktLhddi3kGOWdX3ww/yqgYGSnEnsWWdsYioqsdnqM81dhNLay\nlbht3SK+kzPSQexMdKONYH0CgYAS1lKk+Ie8lICigM1tK0SE9XSTpyEA4KLQKkKk\ngdjP5ixxPArQHu2Pf4kB5mgmlbQ2NF3oRpfjekZc9fUV4hARCucpvXcw9MMPRVyM\n01CQSzZzjk3ULuAQTy+B7lwOh+6Q5iZUaZe7ANfUudR4C/5nbHFHrvD7RW9YVKRL\nAuiXhQKBgDMFeZRfu/dhTdVQ9XZigOWvkeXYxxoloiIHIg3ByZwEAlH/RnlA0M1Z\nOaLt/Q1KNh2UDKkstfOAJ1FdqLm3JU0Hqx/D8dpvTUQBkqoMf8U1WQC2WVmlpmUv\ndrIj1d5/r2N1Cxorx0IbVWsW7WPVM/lVyBU7+2QsKoI5YIervsJY\n-----END RSA PRIVATE KEY-----\n", + "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIfSTUs4gsNNWWLk2Wpy9F2hFzZoyfkjlmEmycE27MHbwPoV0ARuMOf+/508rnwvhYagYykeqTjuY0OB1MiR8/kEGBu5CkFSauwJmfxBVGmpncRIJeycys6OthGpN6Wq4ZZH3Em8gnA3PdRswTZzxJg49ze0ewg3KfxO3aywDwv0qNxN7oLM2lsI1tnpDejv+Kxg/v2iCIVj5Ucreu0FjXtob1sPHm9x7xGgivjre7/5r6Nhc+7NmCd1O07cQ/CrhOLWnJ2m4mj09iHWJjpE/dc8xg3CmgpOhjPIRJ6qrCiWbP6eESH+tC27DBbvTjcgz7rbD1Q+Qda/bymoNnEHGH m0nk3y@sshkeys-11\n", + "user": "m0nk3y" + }, + { + "ip": "10.2.2.42", + "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA5fmqwJV/NZOThZ0B0SXJ7jz+xp2zvVI+DR141JpEJGAm8xP8\nCMmDACkGVDZfwQQEWsmG6WHsRJnBTm1jawUbhgD8EGYNp9sj8G4oW6GvThzzlZvp\nABgtSyWtT6CLBoF7t3/wgFXfAaA33lTg/Ht+bXBMaAZiHyRlexPjmtfhu1Hw44cM\nBuxJwA31OqnO0OPKOh6wW0OWta9BsJnFBckEve1y2Bf2SOnFdlAEV9tNWwGt/AK8\nMAEpgwEZXISrqOucjn7YGEzfZ+Ygjq4/M3FGE31ttrTgERqAPchd1Cp6da6mlYtu\nzx35spV2kxf2ydYHYOOgvS8cCIIk7GIANZztmQIDAQABAoIBAQCAOcXQHUrRV5hw\nbkt+DuDZWd8AZRu7mqiIbX9aoy0NTyNIc0MaryjApR8nQy3+k7vN1wHHDNdMpKIY\nlXtSR4XCILhqeExy5AfU3cbY2HzDQ/c42rZ+W/ydIsPQWwZJOVb+yHITTE3MPUYJ\nTDAp9r1WTb/8XFrHXGbMyhkk0+vDoezj+FDS0YbFImt2iFgC7wgDjuoG5CnlW09/\n/r2bfH/qKKvs9sDwCypVqH5bki1VyQLRfdrCgPisBnhBAj8OBFN+IN5L3P+Zv5UI\nwyZA34RETijHb158vAtIfz2LT0Gin6CNGZY+QOOjM1hCevgrbLeD13Bc9Oog7367\nlm10eMKBAoGBAPUPrbpgA/rg77YrL7uBQhy13HtrRnxW4AjtDs/dEelXlF/Zdfi6\nzukVkb6PaYVPAOC58E21gOJNDYXUdwkbGrJSIDr6rfb9AeEnGIcyDPn36roLjGBn\nJO3Ikr4AhycjbQVVdvo4VY5baCtHNonbn4VFeb+ThszMOQWci4djPGWJAoGBAPA9\nmbboApqV/zoy4PAukFFWOUxb+3GxwcywlVYIuAk3DfM5zJuLgxV70KJ/Z6ppmTzF\n+uPkydTFQv/aLA3IiUioPijl2/l1HmspHpzQztdJaMHhFolKCB+X7wa7QlSFKKyE\ngT8dV8mPsW2HMoNv/yfVQ7lv2M9t4CKhzgssnFORAoGAbeqJXqYAQv+vJQM71ptE\nXwJHEWhtZgnFVNuXIC6lAQdSOqecHWMUuUD+bP2AM9Xaq/FaUlCNrXMoFJXWilQI\n5mClqi6T5stWk3lorAMMBPZo5ueVIAxDaQ/kmao89JYUKSdLRTINVduz3m2DjdPf\nOfSOhhoShTs4fEbZ4nDlPxkCgYEAhz1WM/YFyToZVIzhvbOowHD2jnrVYJp9i5n4\nZ1c/KsjYTIzEFugBoe1ydJeeJvuNLP4Sj4ny6Jknb1pFJHk4dzNm0qUbISICPrcG\nKacOWXlUxJfOlPic/BQOlc6Ct4vCauOo0nvVOH1wl0Tddcpta+INXu2MsrCa1UQa\n9oVld1ECgYADhllIDq3mkM4y58BSIOQ7uOKqbOgTyOjUCS2cFtYXtv6UY/OxFVxJ\n9soergMdd1uDOOwv96Yu9aNzgqjXFixb3Gyk+xh1viOpLrpbCUgg6j20IHcv8pwS\nhsp2wHDCuS8cKK9E8RJ3YYNgLh5uH1J+GhzSix1V8sizT0Y1UPOCDQ==\n-----END RSA PRIVATE KEY-----\n", + "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDl+arAlX81k5OFnQHRJcnuPP7GnbO9Uj4NHXjUmkQkYCbzE/wIyYMAKQZUNl/BBARayYbpYexEmcFObWNrBRuGAPwQZg2n2yPwbihboa9OHPOVm+kAGC1LJa1PoIsGgXu3f/CAVd8BoDfeVOD8e35tcExoBmIfJGV7E+Oa1+G7UfDjhwwG7EnADfU6qc7Q48o6HrBbQ5a1r0GwmcUFyQS97XLYF/ZI6cV2UARX201bAa38ArwwASmDARlchKuo65yOftgYTN9n5iCOrj8zcUYTfW22tOARGoA9yF3UKnp1rqaVi27PHfmylXaTF/bJ1gdg46C9LxwIgiTsYgA1nO2Z m0nk3y@sshkeys-12\n", + "user": "m0nk3y" + } + ] + }, + "general": { + "keep_tunnel_open_time": 60, + "monkey_dir_name": "monkey_dir", + "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" + }, + "kill_file": { + "kill_file_path_linux": "/var/run/monkey.not", + "kill_file_path_windows": "%windir%\\monkey.not" + }, + "logging": { + "dropper_log_path_linux": "/tmp/user-1562", + "dropper_log_path_windows": "%temp%\\~df1562.tmp", + "monkey_log_path_linux": "/tmp/user-1563", + "monkey_log_path_windows": "%temp%\\~df1563.tmp", + "send_log_to_server": true + } + }, + "monkey": { + "behaviour": { + "PBA_linux_filename": "", + "PBA_windows_filename": "", + "custom_PBA_linux_cmd": "", + "custom_PBA_windows_cmd": "", + "self_delete_in_cleanup": true, + "serialize_config": false, + "use_file_logging": true + }, + "general": { + "alive": true, + "post_breach_actions": [] + }, + "life_cycle": { + "max_iterations": 1, + "retry_failed_explotation": true, + "timeout_between_iterations": 100, + "victims_max_exploit": 7, + "victims_max_find": 30 + }, + "system_info": { + "collect_system_info": true, + "extract_azure_creds": true, + "should_use_mimikatz": true + } + }, + "network": { + "ping_scanner": { + "ping_scan_timeout": 1000 + }, + "tcp_scanner": { + "HTTP_PORTS": [ + 80, + 8080, + 443, + 8008, + 7001 + ], + "tcp_scan_get_banner": true, + "tcp_scan_interval": 0, + "tcp_scan_timeout": 3000, + "tcp_target_ports": [ + 22, + 2222, + 445, + 135, + 3389, + 80, + 8080, + 443, + 8008, + 3306, + 9200, + 7001 + ] + } + } +} \ No newline at end of file diff --git a/envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf b/envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf new file mode 100644 index 000000000..d47becb64 --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf @@ -0,0 +1,193 @@ +{ + "basic": { + "credentials": { + "exploit_password_list": [ + "Password1!", + "1234", + "password", + "12345678" + ], + "exploit_user_list": [ + "Administrator", + "root", + "user" + ] + }, + "general": { + "should_exploit": true + } + }, + "basic_network": { + "general": { + "blocked_ips": [], + "depth": 2, + "local_network_scan": false, + "subnet_scan_list": [ + "10.2.2.9", + "10.2.2.11" + ] + }, + "network_analysis": { + "inaccessible_subnets": [] + } + }, + "cnc": { + "servers": { + "command_servers": [ + "10.2.2.251:5000" + ], + "current_server": "10.2.2.251:5000", + "internet_services": [ + "monkey.guardicore.com", + "www.google.com" + ] + } + }, + "exploits": { + "general": { + "exploiter_classes": [ + "SmbExploiter", + "WmiExploiter", + "SSHExploiter", + "ShellShockExploiter", + "SambaCryExploiter", + "ElasticGroovyExploiter", + "Struts2Exploiter", + "WebLogicExploiter", + "HadoopExploiter", + "VSFTPDExploiter" + ], + "skip_exploit_if_file_exist": false + }, + "ms08_067": { + "ms08_067_exploit_attempts": 5, + "remote_user_pass": "Password1!", + "user_to_add": "Monkey_IUSER_SUPPORT" + }, + "rdp_grinder": { + "rdp_use_vbs_download": true + }, + "sambacry": { + "sambacry_folder_paths_to_guess": [ + "/", + "/mnt", + "/tmp", + "/storage", + "/export", + "/share", + "/shares", + "/home" + ], + "sambacry_shares_not_to_check": [ + "IPC$", + "print$" + ], + "sambacry_trigger_timeout": 5 + }, + "smb_service": { + "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey" + } + }, + "internal": { + "classes": { + "finger_classes": [ + "SMBFinger", + "SSHFinger", + "PingScanner", + "HTTPFinger", + "MySQLFinger", + "MSSQLFinger", + "ElasticFinger" + ] + }, + "dropper": { + "dropper_date_reference_path_linux": "/bin/sh", + "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", + "dropper_set_date": true, + "dropper_target_path_linux": "/tmp/monkey", + "dropper_target_path_win_32": "C:\\Windows\\temp\\monkey32.exe", + "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", + "dropper_try_move_first": true + }, + "exploits": { + "exploit_lm_hash_list": [], + "exploit_ntlm_hash_list": [], + "exploit_ssh_keys": [] + }, + "general": { + "keep_tunnel_open_time": 60, + "monkey_dir_name": "monkey_dir", + "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" + }, + "kill_file": { + "kill_file_path_linux": "/var/run/monkey.not", + "kill_file_path_windows": "%windir%\\monkey.not" + }, + "logging": { + "dropper_log_path_linux": "/tmp/user-1562", + "dropper_log_path_windows": "%temp%\\~df1562.tmp", + "monkey_log_path_linux": "/tmp/user-1563", + "monkey_log_path_windows": "%temp%\\~df1563.tmp", + "send_log_to_server": true + } + }, + "monkey": { + "behaviour": { + "PBA_linux_filename": "", + "PBA_windows_filename": "", + "custom_PBA_linux_cmd": "", + "custom_PBA_windows_cmd": "", + "self_delete_in_cleanup": true, + "serialize_config": false, + "use_file_logging": true + }, + "general": { + "alive": true, + "post_breach_actions": [] + }, + "life_cycle": { + "max_iterations": 1, + "retry_failed_explotation": true, + "timeout_between_iterations": 100, + "victims_max_exploit": 7, + "victims_max_find": 30 + }, + "system_info": { + "collect_system_info": true, + "extract_azure_creds": true, + "should_use_mimikatz": true + } + }, + "network": { + "ping_scanner": { + "ping_scan_timeout": 1000 + }, + "tcp_scanner": { + "HTTP_PORTS": [ + 80, + 8080, + 443, + 8008, + 7001 + ], + "tcp_scan_get_banner": true, + "tcp_scan_interval": 0, + "tcp_scan_timeout": 3000, + "tcp_target_ports": [ + 22, + 2222, + 445, + 135, + 3389, + 80, + 8080, + 443, + 8008, + 3306, + 9200, + 7001 + ] + } + } +} \ No newline at end of file diff --git a/envs/monkey_zoo/blackbox/island_configs/TUNNELING.conf b/envs/monkey_zoo/blackbox/island_configs/TUNNELING.conf new file mode 100644 index 000000000..62dd40e30 --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_configs/TUNNELING.conf @@ -0,0 +1,194 @@ +{ + "basic": { + "credentials": { + "exploit_password_list": [ + "Password1!", + "3Q=(Ge(+&w]*", + "`))jU7L(w}", + "12345678" + ], + "exploit_user_list": [ + "Administrator", + "m0nk3y", + "user" + ] + }, + "general": { + "should_exploit": true + } + }, + "basic_network": { + "general": { + "blocked_ips": [], + "depth": 3, + "local_network_scan": false, + "subnet_scan_list": [ + "10.2.2.39", + "10.2.1.10", + "10.2.0.11" + ] + }, + "network_analysis": { + "inaccessible_subnets": [] + } + }, + "cnc": { + "servers": { + "command_servers": [ + "10.2.2.251:5000" + ], + "current_server": "10.2.2.251:5000", + "internet_services": [ + "monkey.guardicore.com", + "www.google.com" + ] + } + }, + "exploits": { + "general": { + "exploiter_classes": [ + "SmbExploiter", + "WmiExploiter", + "SSHExploiter", + "ShellShockExploiter", + "SambaCryExploiter", + "ElasticGroovyExploiter", + "Struts2Exploiter", + "WebLogicExploiter", + "HadoopExploiter", + "VSFTPDExploiter" + ], + "skip_exploit_if_file_exist": false + }, + "ms08_067": { + "ms08_067_exploit_attempts": 5, + "remote_user_pass": "Password1!", + "user_to_add": "Monkey_IUSER_SUPPORT" + }, + "rdp_grinder": { + "rdp_use_vbs_download": true + }, + "sambacry": { + "sambacry_folder_paths_to_guess": [ + "/", + "/mnt", + "/tmp", + "/storage", + "/export", + "/share", + "/shares", + "/home" + ], + "sambacry_shares_not_to_check": [ + "IPC$", + "print$" + ], + "sambacry_trigger_timeout": 5 + }, + "smb_service": { + "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey" + } + }, + "internal": { + "classes": { + "finger_classes": [ + "SMBFinger", + "SSHFinger", + "PingScanner", + "HTTPFinger", + "MySQLFinger", + "MSSQLFinger", + "ElasticFinger" + ] + }, + "dropper": { + "dropper_date_reference_path_linux": "/bin/sh", + "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", + "dropper_set_date": true, + "dropper_target_path_linux": "/tmp/monkey", + "dropper_target_path_win_32": "C:\\Windows\\temp\\monkey32.exe", + "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", + "dropper_try_move_first": true + }, + "exploits": { + "exploit_lm_hash_list": [], + "exploit_ntlm_hash_list": [], + "exploit_ssh_keys": [] + }, + "general": { + "keep_tunnel_open_time": 60, + "monkey_dir_name": "monkey_dir", + "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" + }, + "kill_file": { + "kill_file_path_linux": "/var/run/monkey.not", + "kill_file_path_windows": "%windir%\\monkey.not" + }, + "logging": { + "dropper_log_path_linux": "/tmp/user-1562", + "dropper_log_path_windows": "%temp%\\~df1562.tmp", + "monkey_log_path_linux": "/tmp/user-1563", + "monkey_log_path_windows": "%temp%\\~df1563.tmp", + "send_log_to_server": true + } + }, + "monkey": { + "behaviour": { + "PBA_linux_filename": "", + "PBA_windows_filename": "", + "custom_PBA_linux_cmd": "", + "custom_PBA_windows_cmd": "", + "self_delete_in_cleanup": true, + "serialize_config": false, + "use_file_logging": true + }, + "general": { + "alive": true, + "post_breach_actions": [] + }, + "life_cycle": { + "max_iterations": 1, + "retry_failed_explotation": true, + "timeout_between_iterations": 100, + "victims_max_exploit": 7, + "victims_max_find": 30 + }, + "system_info": { + "collect_system_info": true, + "extract_azure_creds": true, + "should_use_mimikatz": true + } + }, + "network": { + "ping_scanner": { + "ping_scan_timeout": 1000 + }, + "tcp_scanner": { + "HTTP_PORTS": [ + 80, + 8080, + 443, + 8008, + 7001 + ], + "tcp_scan_get_banner": true, + "tcp_scan_interval": 0, + "tcp_scan_timeout": 3000, + "tcp_target_ports": [ + 22, + 2222, + 445, + 135, + 3389, + 80, + 8080, + 443, + 8008, + 3306, + 9200, + 7001 + ] + } + } +} \ No newline at end of file diff --git a/envs/monkey_zoo/blackbox/island_configs/WEBLOGIC.conf b/envs/monkey_zoo/blackbox/island_configs/WEBLOGIC.conf new file mode 100644 index 000000000..50ad122e4 --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_configs/WEBLOGIC.conf @@ -0,0 +1,184 @@ +{ + "basic": { + "credentials": { + "exploit_password_list": [ + "Password1!", + "1234", + "password", + "12345678" + ], + "exploit_user_list": [ + "Administrator", + "root", + "user" + ] + }, + "general": { + "should_exploit": true + } + }, + "basic_network": { + "general": { + "blocked_ips": [], + "depth": 2, + "local_network_scan": false, + "subnet_scan_list": [ + "10.2.2.18", + "10.2.2.19" + ] + }, + "network_analysis": { + "inaccessible_subnets": [] + } + }, + "cnc": { + "servers": { + "command_servers": [ + "10.2.2.251:5000" + ], + "current_server": "10.2.2.251:5000", + "internet_services": [ + "monkey.guardicore.com", + "www.google.com" + ] + } + }, + "exploits": { + "general": { + "exploiter_classes": [ + "WebLogicExploiter" + ], + "skip_exploit_if_file_exist": false + }, + "ms08_067": { + "ms08_067_exploit_attempts": 5, + "remote_user_pass": "Password1!", + "user_to_add": "Monkey_IUSER_SUPPORT" + }, + "rdp_grinder": { + "rdp_use_vbs_download": true + }, + "sambacry": { + "sambacry_folder_paths_to_guess": [ + "/", + "/mnt", + "/tmp", + "/storage", + "/export", + "/share", + "/shares", + "/home" + ], + "sambacry_shares_not_to_check": [ + "IPC$", + "print$" + ], + "sambacry_trigger_timeout": 5 + }, + "smb_service": { + "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey" + } + }, + "internal": { + "classes": { + "finger_classes": [ + "SMBFinger", + "SSHFinger", + "PingScanner", + "HTTPFinger", + "MySQLFinger", + "MSSQLFinger", + "ElasticFinger" + ] + }, + "dropper": { + "dropper_date_reference_path_linux": "/bin/sh", + "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", + "dropper_set_date": true, + "dropper_target_path_linux": "/tmp/monkey", + "dropper_target_path_win_32": "C:\\Windows\\temp\\monkey32.exe", + "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", + "dropper_try_move_first": true + }, + "exploits": { + "exploit_lm_hash_list": [], + "exploit_ntlm_hash_list": [], + "exploit_ssh_keys": [] + }, + "general": { + "keep_tunnel_open_time": 60, + "monkey_dir_name": "monkey_dir", + "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" + }, + "kill_file": { + "kill_file_path_linux": "/var/run/monkey.not", + "kill_file_path_windows": "%windir%\\monkey.not" + }, + "logging": { + "dropper_log_path_linux": "/tmp/user-1562", + "dropper_log_path_windows": "%temp%\\~df1562.tmp", + "monkey_log_path_linux": "/tmp/user-1563", + "monkey_log_path_windows": "%temp%\\~df1563.tmp", + "send_log_to_server": true + } + }, + "monkey": { + "behaviour": { + "PBA_linux_filename": "", + "PBA_windows_filename": "", + "custom_PBA_linux_cmd": "", + "custom_PBA_windows_cmd": "", + "self_delete_in_cleanup": true, + "serialize_config": false, + "use_file_logging": true + }, + "general": { + "alive": true, + "post_breach_actions": [] + }, + "life_cycle": { + "max_iterations": 1, + "retry_failed_explotation": true, + "timeout_between_iterations": 100, + "victims_max_exploit": 7, + "victims_max_find": 30 + }, + "system_info": { + "collect_system_info": true, + "extract_azure_creds": true, + "should_use_mimikatz": true + } + }, + "network": { + "ping_scanner": { + "ping_scan_timeout": 1000 + }, + "tcp_scanner": { + "HTTP_PORTS": [ + 80, + 8080, + 443, + 8008, + 7001 + ], + "tcp_scan_get_banner": true, + "tcp_scan_interval": 0, + "tcp_scan_timeout": 3000, + "tcp_target_ports": [ + 22, + 2222, + 445, + 135, + 3389, + 80, + 8080, + 443, + 8008, + 3306, + 9200, + 7001 + ] + } + } +} \ No newline at end of file diff --git a/envs/monkey_zoo/blackbox/island_configs/WMI_MIMIKATZ.conf b/envs/monkey_zoo/blackbox/island_configs/WMI_MIMIKATZ.conf new file mode 100644 index 000000000..3e3b8c103 --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_configs/WMI_MIMIKATZ.conf @@ -0,0 +1,192 @@ +{ + "basic": { + "credentials": { + "exploit_password_list": [ + "Password1!", + "Ivrrw5zEzs" + ], + "exploit_user_list": [ + "Administrator", + "m0nk3y", + "user" + ] + }, + "general": { + "should_exploit": true + } + }, + "basic_network": { + "general": { + "blocked_ips": [], + "depth": 2, + "local_network_scan": false, + "subnet_scan_list": [ + "10.2.2.44", + "10.2.2.15" + ] + }, + "network_analysis": { + "inaccessible_subnets": [] + } + }, + "cnc": { + "servers": { + "command_servers": [ + "10.2.2.251:5000" + ], + "current_server": "10.2.2.251:5000", + "internet_services": [ + "monkey.guardicore.com", + "www.google.com" + ] + } + }, + "exploits": { + "general": { + "exploiter_classes": [ + "WmiExploiter", + "SSHExploiter", + "ShellShockExploiter", + "SambaCryExploiter", + "ElasticGroovyExploiter", + "Struts2Exploiter", + "WebLogicExploiter", + "HadoopExploiter", + "VSFTPDExploiter" + ], + "skip_exploit_if_file_exist": false + }, + "ms08_067": { + "ms08_067_exploit_attempts": 5, + "remote_user_pass": "Password1!", + "user_to_add": "Monkey_IUSER_SUPPORT" + }, + "rdp_grinder": { + "rdp_use_vbs_download": true + }, + "sambacry": { + "sambacry_folder_paths_to_guess": [ + "/", + "/mnt", + "/tmp", + "/storage", + "/export", + "/share", + "/shares", + "/home" + ], + "sambacry_shares_not_to_check": [ + "IPC$", + "print$" + ], + "sambacry_trigger_timeout": 5 + }, + "smb_service": { + "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey" + } + }, + "internal": { + "classes": { + "finger_classes": [ + "SMBFinger", + "SSHFinger", + "PingScanner", + "HTTPFinger", + "MySQLFinger", + "MSSQLFinger", + "ElasticFinger" + ] + }, + "dropper": { + "dropper_date_reference_path_linux": "/bin/sh", + "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", + "dropper_set_date": true, + "dropper_target_path_linux": "/tmp/monkey", + "dropper_target_path_win_32": "C:\\Windows\\temp\\monkey32.exe", + "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", + "dropper_try_move_first": true + }, + "exploits": { + "exploit_lm_hash_list": [], + "exploit_ntlm_hash_list": [ + "5da0889ea2081aa79f6852294cba4a5e" + ], + "exploit_ssh_keys": [] + }, + "general": { + "keep_tunnel_open_time": 60, + "monkey_dir_name": "monkey_dir", + "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" + }, + "kill_file": { + "kill_file_path_linux": "/var/run/monkey.not", + "kill_file_path_windows": "%windir%\\monkey.not" + }, + "logging": { + "dropper_log_path_linux": "/tmp/user-1562", + "dropper_log_path_windows": "%temp%\\~df1562.tmp", + "monkey_log_path_linux": "/tmp/user-1563", + "monkey_log_path_windows": "%temp%\\~df1563.tmp", + "send_log_to_server": true + } + }, + "monkey": { + "behaviour": { + "PBA_linux_filename": "", + "PBA_windows_filename": "", + "custom_PBA_linux_cmd": "", + "custom_PBA_windows_cmd": "", + "self_delete_in_cleanup": true, + "serialize_config": false, + "use_file_logging": true + }, + "general": { + "alive": true, + "post_breach_actions": [] + }, + "life_cycle": { + "max_iterations": 2, + "retry_failed_explotation": true, + "timeout_between_iterations": 100, + "victims_max_exploit": 7, + "victims_max_find": 30 + }, + "system_info": { + "collect_system_info": true, + "extract_azure_creds": true, + "should_use_mimikatz": true + } + }, + "network": { + "ping_scanner": { + "ping_scan_timeout": 1000 + }, + "tcp_scanner": { + "HTTP_PORTS": [ + 80, + 8080, + 443, + 8008, + 7001 + ], + "tcp_scan_get_banner": true, + "tcp_scan_interval": 0, + "tcp_scan_timeout": 3000, + "tcp_target_ports": [ + 22, + 2222, + 445, + 135, + 3389, + 80, + 8080, + 443, + 8008, + 3306, + 9200, + 7001 + ] + } + } +} \ No newline at end of file From 98a60a37dfa4a0160f0a4add6efacbcfa5dddd98 Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Thu, 29 Aug 2019 14:57:04 +0300 Subject: [PATCH 08/25] Works talking to server --- envs/monkey_zoo/blackbox/conftest.py | 10 +++++ envs/monkey_zoo/blackbox/test_blackbox.py | 48 ++++++++++++++++++----- 2 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 envs/monkey_zoo/blackbox/conftest.py diff --git a/envs/monkey_zoo/blackbox/conftest.py b/envs/monkey_zoo/blackbox/conftest.py new file mode 100644 index 000000000..b15e9fdef --- /dev/null +++ b/envs/monkey_zoo/blackbox/conftest.py @@ -0,0 +1,10 @@ +def pytest_addoption(parser): + parser.addoption("--island", action="store", default="default name") + + +def pytest_generate_tests(metafunc): + # This is called for every test. Only get/set command line arguments + # if the argument is specified in the list of test "fixturenames". + option_value = metafunc.config.option.name + if 'name' in metafunc.fixturenames and option_value is not None: + metafunc.parametrize("island", [option_value]) \ No newline at end of file diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index a9afd5244..7fba9035e 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -6,38 +6,68 @@ import requests from config import * +# SHA3-512 of '1234567890!@#$%^&*()_nothing_up_my_sleeve_1234567890!@#$%^&*()' +NO_AUTH_CREDS = '55e97c9dcfd22b8079189ddaeea9bce8125887e3237b800c6176c9afa80d2062' \ + '8d2c8d0b1538d2208c1444ac66535b764a3d902b35e751df3faec1e477ed3557' -def generic_blackbox_test_case(config_file_path, analyzers): - load_config_into_server(config_file_path) + +def generic_blackbox_test_case(client, config_file_path, analyzers): + load_config_into_server(client, config_file_path) run_local_monkey_on_island() for analyzer in analyzers: assert analyzer.analyze_test_results() -class TestMonkeyBlackbox(unittest.TestCase): +class MonkeyIslandClient(object): + def __init__(self, server_address): + self.addr = "https://{IP}/".format(IP=server_address) + self.token = self.get_jwt_token_from_server() + def get_jwt_token_from_server(self): + resp = requests.post(self.addr + "api/auth", json={"username": NO_AUTH_CREDS, "password": NO_AUTH_CREDS}, verify=False) + return resp.json()["access_token"] + + def get_api_status(self): + return requests.get(self.addr + "api", headers={"Authorization": "JWT " + self.token}, verify=False) + + def import_config(self, config_contents): + resp = requests.post( + self.addr + "api/configuration/island", + headers={"Authorization": "JWT " + self.token}, + data=config_contents, + verify=False) + print(resp.text) + + +class TestMonkeyBlackbox(unittest.TestCase): @classmethod def setUpClass(cls): - GCPHandler().start_machines("elastic-4") + #GCPHandler().start_machines("elastic-4") print("Setting up all GCP machines...") @classmethod def tearDownClass(cls): - GCPHandler().stop_machines("elastic-4") + #GCPHandler().stop_machines("elastic-4") print("Killing all GCP machines...") + def test_server_online(self): + client = MonkeyIslandClient(ISLAND_SERVER_ADDRESS) + assert client.get_api_status() is not None + def test_ssh_exec(self): - conf_file_name = "ssh.conf" - generic_blackbox_test_case(get_conf_file_path(conf_file_name), []) + client = MonkeyIslandClient(ISLAND_SERVER_ADDRESS) + conf_file_name = "SSH.conf" + generic_blackbox_test_case(client, get_conf_file_path(conf_file_name), []) def run_local_monkey_on_island(): print("Trying to run local monkey on {}".format(ISLAND_SERVER_ADDRESS)) - print(ISLAND_SERVER_URL + "api") -def load_config_into_server(config_file_path): +def load_config_into_server(client, config_file_path): print("uploading {} to {}".format(config_file_path, ISLAND_SERVER_ADDRESS)) + with open(config_file_path, "r") as config_file: + client.import_config(config_file.read()) def get_conf_file_path(conf_file_name): From ebd2628516f94c3282fa8575b1dbcd790dd80b48 Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Thu, 29 Aug 2019 15:14:07 +0300 Subject: [PATCH 09/25] Now pytest gets --island 1.2.3.4:5000 as command line param --- envs/__init__.py | 0 envs/monkey_zoo/__init__.py | 0 envs/monkey_zoo/blackbox/config.py | 2 - envs/monkey_zoo/blackbox/conftest.py | 15 ++--- .../blackbox/monkey_island_client.py | 27 +++++++++ envs/monkey_zoo/blackbox/test_blackbox.py | 55 ++++--------------- 6 files changed, 46 insertions(+), 53 deletions(-) create mode 100644 envs/__init__.py create mode 100644 envs/monkey_zoo/__init__.py delete mode 100644 envs/monkey_zoo/blackbox/config.py create mode 100644 envs/monkey_zoo/blackbox/monkey_island_client.py diff --git a/envs/__init__.py b/envs/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/envs/monkey_zoo/__init__.py b/envs/monkey_zoo/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/envs/monkey_zoo/blackbox/config.py b/envs/monkey_zoo/blackbox/config.py deleted file mode 100644 index 2a38498fd..000000000 --- a/envs/monkey_zoo/blackbox/config.py +++ /dev/null @@ -1,2 +0,0 @@ -ISLAND_SERVER_ADDRESS = "1.2.3.4" -ISLAND_SERVER_URL = "https://{IP}/".format(IP=ISLAND_SERVER_ADDRESS) diff --git a/envs/monkey_zoo/blackbox/conftest.py b/envs/monkey_zoo/blackbox/conftest.py index b15e9fdef..ccbbe694a 100644 --- a/envs/monkey_zoo/blackbox/conftest.py +++ b/envs/monkey_zoo/blackbox/conftest.py @@ -1,10 +1,11 @@ +import pytest + + def pytest_addoption(parser): - parser.addoption("--island", action="store", default="default name") + parser.addoption("--island", action="store", default="", + help="Specify the Monkey Island address (host+port).") -def pytest_generate_tests(metafunc): - # This is called for every test. Only get/set command line arguments - # if the argument is specified in the list of test "fixturenames". - option_value = metafunc.config.option.name - if 'name' in metafunc.fixturenames and option_value is not None: - metafunc.parametrize("island", [option_value]) \ No newline at end of file +@pytest.fixture +def island(request): + request.cls.island = request.config.getoption("--island") diff --git a/envs/monkey_zoo/blackbox/monkey_island_client.py b/envs/monkey_zoo/blackbox/monkey_island_client.py new file mode 100644 index 000000000..582b3a0dc --- /dev/null +++ b/envs/monkey_zoo/blackbox/monkey_island_client.py @@ -0,0 +1,27 @@ +import requests + +# SHA3-512 of '1234567890!@#$%^&*()_nothing_up_my_sleeve_1234567890!@#$%^&*()' +NO_AUTH_CREDS = '55e97c9dcfd22b8079189ddaeea9bce8125887e3237b800c6176c9afa80d2062' \ + '8d2c8d0b1538d2208c1444ac66535b764a3d902b35e751df3faec1e477ed3557' + + +class MonkeyIslandClient(object): + def __init__(self, server_address): + self.addr = "https://{IP}/".format(IP=server_address) + self.token = self.get_jwt_token_from_server() + + def get_jwt_token_from_server(self): + resp = requests.post(self.addr + "api/auth", json={"username": NO_AUTH_CREDS, "password": NO_AUTH_CREDS}, + verify=False) + return resp.json()["access_token"] + + def get_api_status(self): + return requests.get(self.addr + "api", headers={"Authorization": "JWT " + self.token}, verify=False) + + def import_config(self, config_contents): + resp = requests.post( + self.addr + "api/configuration/island", + headers={"Authorization": "JWT " + self.token}, + data=config_contents, + verify=False) + print(resp.text) diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index 7fba9035e..cacbfeb4f 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -1,74 +1,41 @@ import os import unittest -from .gcp_machine_handlers import GCPHandler -import requests +import pytest -from config import * - -# SHA3-512 of '1234567890!@#$%^&*()_nothing_up_my_sleeve_1234567890!@#$%^&*()' -NO_AUTH_CREDS = '55e97c9dcfd22b8079189ddaeea9bce8125887e3237b800c6176c9afa80d2062' \ - '8d2c8d0b1538d2208c1444ac66535b764a3d902b35e751df3faec1e477ed3557' +from envs.monkey_zoo.blackbox.monkey_island_client import MonkeyIslandClient def generic_blackbox_test_case(client, config_file_path, analyzers): - load_config_into_server(client, config_file_path) - run_local_monkey_on_island() + with open(config_file_path, "r") as config_file: + client.import_config(config_file.read()) + # run_local_monkey_on_island() for analyzer in analyzers: assert analyzer.analyze_test_results() -class MonkeyIslandClient(object): - def __init__(self, server_address): - self.addr = "https://{IP}/".format(IP=server_address) - self.token = self.get_jwt_token_from_server() - - def get_jwt_token_from_server(self): - resp = requests.post(self.addr + "api/auth", json={"username": NO_AUTH_CREDS, "password": NO_AUTH_CREDS}, verify=False) - return resp.json()["access_token"] - - def get_api_status(self): - return requests.get(self.addr + "api", headers={"Authorization": "JWT " + self.token}, verify=False) - - def import_config(self, config_contents): - resp = requests.post( - self.addr + "api/configuration/island", - headers={"Authorization": "JWT " + self.token}, - data=config_contents, - verify=False) - print(resp.text) - - +@pytest.mark.usefixtures("island") +# noinspection PyUnresolvedReferences class TestMonkeyBlackbox(unittest.TestCase): @classmethod def setUpClass(cls): - #GCPHandler().start_machines("elastic-4") + # GCPHandler().start_machines("elastic-4") print("Setting up all GCP machines...") @classmethod def tearDownClass(cls): - #GCPHandler().stop_machines("elastic-4") + # GCPHandler().stop_machines("elastic-4") print("Killing all GCP machines...") def test_server_online(self): - client = MonkeyIslandClient(ISLAND_SERVER_ADDRESS) + client = MonkeyIslandClient(self.island) assert client.get_api_status() is not None def test_ssh_exec(self): - client = MonkeyIslandClient(ISLAND_SERVER_ADDRESS) + client = MonkeyIslandClient(self.island) conf_file_name = "SSH.conf" generic_blackbox_test_case(client, get_conf_file_path(conf_file_name), []) -def run_local_monkey_on_island(): - print("Trying to run local monkey on {}".format(ISLAND_SERVER_ADDRESS)) - - -def load_config_into_server(client, config_file_path): - print("uploading {} to {}".format(config_file_path, ISLAND_SERVER_ADDRESS)) - with open(config_file_path, "r") as config_file: - client.import_config(config_file.read()) - - def get_conf_file_path(conf_file_name): return os.path.join(os.path.dirname(os.path.abspath(__file__)), "island_configs", conf_file_name) From 919a7ddd1148ad6bba6da421b3c0f6ebeae4d8fe Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Thu, 29 Aug 2019 18:18:25 +0300 Subject: [PATCH 10/25] Carcass of analyzers added --- envs/monkey_zoo/blackbox/analyzers/__init__.py | 0 .../blackbox/analyzers/communication_analyzer.py | 16 ++++++++++++++++ envs/monkey_zoo/blackbox/monkey_island_client.py | 7 +++++++ envs/monkey_zoo/blackbox/test_blackbox.py | 4 +++- 4 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 envs/monkey_zoo/blackbox/analyzers/__init__.py create mode 100644 envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py diff --git a/envs/monkey_zoo/blackbox/analyzers/__init__.py b/envs/monkey_zoo/blackbox/analyzers/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py b/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py new file mode 100644 index 000000000..3afb528f7 --- /dev/null +++ b/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py @@ -0,0 +1,16 @@ + +class CommunicationAnalyzer(object): + + def __init__(self, island_client, machines): + self.island_client = island_client + self.machines = machines + + def analyze_test_results(self): + for machine in self.machines: + if self.did_monkey_communicate_back(machine): + print("Monkey from {} communicated back".format(machine)) + + def did_monkey_communicate_back(self, monkey_ip): + request = self.island_client.send_get_request("api/telemetry", {'telem_category': 'state'}) + + diff --git a/envs/monkey_zoo/blackbox/monkey_island_client.py b/envs/monkey_zoo/blackbox/monkey_island_client.py index 582b3a0dc..b42500934 100644 --- a/envs/monkey_zoo/blackbox/monkey_island_client.py +++ b/envs/monkey_zoo/blackbox/monkey_island_client.py @@ -25,3 +25,10 @@ class MonkeyIslandClient(object): data=config_contents, verify=False) print(resp.text) + + def send_get_request(self, endpoint, data): + resp = requests.get(self.addr + endpoint, + headers={"Authorization": "JWT " + self.token}, + params=data, + verify=False) + return resp diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index cacbfeb4f..8d7366e4e 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -4,6 +4,7 @@ import unittest import pytest from envs.monkey_zoo.blackbox.monkey_island_client import MonkeyIslandClient +from envs.monkey_zoo.blackbox.analyzers.communication_analyzer import CommunicationAnalyzer def generic_blackbox_test_case(client, config_file_path, analyzers): @@ -34,7 +35,8 @@ class TestMonkeyBlackbox(unittest.TestCase): def test_ssh_exec(self): client = MonkeyIslandClient(self.island) conf_file_name = "SSH.conf" - generic_blackbox_test_case(client, get_conf_file_path(conf_file_name), []) + generic_blackbox_test_case(client, get_conf_file_path(conf_file_name), + [CommunicationAnalyzer(client, ["10.2.2.41", "10.2.2.42"])]) def get_conf_file_path(conf_file_name): From 5afded480ea5f22908a5af537ce83b302c938e07 Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Thu, 29 Aug 2019 18:48:35 +0300 Subject: [PATCH 11/25] Now run monkey works --- .../blackbox/monkey_island_client.py | 36 +++++++++++++++---- envs/monkey_zoo/blackbox/test_blackbox.py | 2 +- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/envs/monkey_zoo/blackbox/monkey_island_client.py b/envs/monkey_zoo/blackbox/monkey_island_client.py index 582b3a0dc..c2cde2506 100644 --- a/envs/monkey_zoo/blackbox/monkey_island_client.py +++ b/envs/monkey_zoo/blackbox/monkey_island_client.py @@ -1,3 +1,5 @@ +import json + import requests # SHA3-512 of '1234567890!@#$%^&*()_nothing_up_my_sleeve_1234567890!@#$%^&*()' @@ -15,13 +17,35 @@ class MonkeyIslandClient(object): verify=False) return resp.json()["access_token"] + def request_get(self, url): + return requests.get( + self.addr + url, + headers={"Authorization": "JWT " + self.token}, + verify=False + ) + + def request_post(self, url, data): + return requests.post( + self.addr + url, + data=data, + headers={"Authorization": "JWT " + self.token}, + verify=False + ) + + def request_json(self, url, dict_data): + return requests.post( + self.addr + url, + json=dict_data, + headers={"Authorization": "JWT " + self.token}, + verify=False + ) + def get_api_status(self): - return requests.get(self.addr + "api", headers={"Authorization": "JWT " + self.token}, verify=False) + return self.request_get("api") def import_config(self, config_contents): - resp = requests.post( - self.addr + "api/configuration/island", - headers={"Authorization": "JWT " + self.token}, - data=config_contents, - verify=False) + _ = self.request_post("api/configuration/island", data=config_contents) + + def run_monkey_local(self): + resp = self.request_json("api/local-monkey", dict_data={"action": "run"}) print(resp.text) diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index cacbfeb4f..15f0f276c 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -9,7 +9,7 @@ from envs.monkey_zoo.blackbox.monkey_island_client import MonkeyIslandClient def generic_blackbox_test_case(client, config_file_path, analyzers): with open(config_file_path, "r") as config_file: client.import_config(config_file.read()) - # run_local_monkey_on_island() + client.run_monkey_local() for analyzer in analyzers: assert analyzer.analyze_test_results() From 772880f95227eb404b52a0f0226913564242e746 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Thu, 5 Sep 2019 15:03:30 +0300 Subject: [PATCH 12/25] Added resources explicitly for testing, improved analyzer, added config parser class --- .../analyzers/communication_analyzer.py | 20 ++++++++++++------- .../blackbox/island_config_parser.py | 16 +++++++++++++++ envs/monkey_zoo/blackbox/test_blackbox.py | 18 ++++++++--------- monkey/monkey_island/cc/app.py | 2 ++ .../cc/resources/test/__init__.py | 0 .../cc/resources/test/monkey_test.py | 14 +++++++++++++ 6 files changed, 53 insertions(+), 17 deletions(-) create mode 100644 envs/monkey_zoo/blackbox/island_config_parser.py create mode 100644 monkey/monkey_island/cc/resources/test/__init__.py create mode 100644 monkey/monkey_island/cc/resources/test/monkey_test.py diff --git a/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py b/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py index 3afb528f7..e4638233f 100644 --- a/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py +++ b/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py @@ -1,16 +1,22 @@ +import json + class CommunicationAnalyzer(object): - def __init__(self, island_client, machines): + def __init__(self, island_client, machine_ips): self.island_client = island_client - self.machines = machines + self.machine_ips = machine_ips def analyze_test_results(self): - for machine in self.machines: - if self.did_monkey_communicate_back(machine): - print("Monkey from {} communicated back".format(machine)) + for machine_ip in self.machine_ips: + if not self.did_monkey_communicate_back(machine_ip): + return False + print("Monkey from {} communicated back".format(machine_ip)) + return True - def did_monkey_communicate_back(self, monkey_ip): - request = self.island_client.send_get_request("api/telemetry", {'telem_category': 'state'}) + def did_monkey_communicate_back(self, machine_ip): + query = json.dumps({'ip_addresses': {'$elemMatch': {'$eq': machine_ip}}}) + response = self.island_client.send_get_request("api/test/monkey", {'find_query': query}) + return len(json.loads(response.content)['results']) > 0 diff --git a/envs/monkey_zoo/blackbox/island_config_parser.py b/envs/monkey_zoo/blackbox/island_config_parser.py new file mode 100644 index 000000000..63c98cb75 --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_config_parser.py @@ -0,0 +1,16 @@ +import json +import os + + +class IslandConfigParser(object): + + def __init__(self, config_filename): + self.config_raw = open(IslandConfigParser.get_conf_file_path(config_filename), 'r').read() + self.config_json = json.loads(self.config_raw) + + def get_ips_of_targets(self): + return self.config_json['basic_network']['general']['subnet_scan_list'] + + @staticmethod + def get_conf_file_path(conf_file_name): + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "island_configs", conf_file_name) diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index 708cbca24..5ef7e16f5 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -1,16 +1,15 @@ -import os import unittest import pytest from envs.monkey_zoo.blackbox.monkey_island_client import MonkeyIslandClient from envs.monkey_zoo.blackbox.analyzers.communication_analyzer import CommunicationAnalyzer +from envs.monkey_zoo.blackbox.island_config_parser import IslandConfigParser -def generic_blackbox_test_case(client, config_file_path, analyzers): - with open(config_file_path, "r") as config_file: - client.import_config(config_file.read()) - client.run_monkey_local() +def generic_blackbox_test_case(client, raw_config, analyzers): + client.import_config(raw_config) + # client.run_monkey_local() for analyzer in analyzers: assert analyzer.analyze_test_results() @@ -33,11 +32,10 @@ class TestMonkeyBlackbox(unittest.TestCase): assert client.get_api_status() is not None def test_ssh_exec(self): + conf_file_name = 'SSH.conf' client = MonkeyIslandClient(self.island) - conf_file_name = "SSH.conf" - generic_blackbox_test_case(client, get_conf_file_path(conf_file_name), - [CommunicationAnalyzer(client, ["10.2.2.41", "10.2.2.42"])]) + config_parser = IslandConfigParser(conf_file_name) + analyzer = CommunicationAnalyzer(client, config_parser.get_ips_of_targets()) + generic_blackbox_test_case(client, config_parser.config_raw, [analyzer]) -def get_conf_file_path(conf_file_name): - return os.path.join(os.path.dirname(os.path.abspath(__file__)), "island_configs", conf_file_name) diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py index 2e04ef0be..7d27995ab 100644 --- a/monkey/monkey_island/cc/app.py +++ b/monkey/monkey_island/cc/app.py @@ -35,6 +35,7 @@ from monkey_island.cc.services.remote_run_aws import RemoteRunAwsService from monkey_island.cc.resources.pba_file_upload import FileUpload from monkey_island.cc.resources.attack.attack_config import AttackConfiguration from monkey_island.cc.resources.attack.attack_report import AttackReport +from monkey_island.cc.resources.test.monkey_test import MonkeyTest __author__ = 'Barak' @@ -134,6 +135,7 @@ def init_api_resources(api): api.add_resource(AttackConfiguration, '/api/attack') api.add_resource(AttackReport, '/api/attack/report') api.add_resource(VersionUpdate, '/api/version-update', '/api/version-update/') + api.add_resource(MonkeyTest, '/api/test/monkey') def init_app(mongo_url): diff --git a/monkey/monkey_island/cc/resources/test/__init__.py b/monkey/monkey_island/cc/resources/test/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/monkey/monkey_island/cc/resources/test/monkey_test.py b/monkey/monkey_island/cc/resources/test/monkey_test.py new file mode 100644 index 000000000..365f30dc9 --- /dev/null +++ b/monkey/monkey_island/cc/resources/test/monkey_test.py @@ -0,0 +1,14 @@ +import json + +import flask_restful +from flask import request + +from monkey_island.cc.auth import jwt_required +from monkey_island.cc.database import mongo + + +class MonkeyTest(flask_restful.Resource): + @jwt_required() + def get(self, **kw): + find_query = json.loads(request.args.get('find_query')) + return {'results': list(mongo.db.monkey.find(find_query))} From 0ee4445ca1dcfc42b1d1e1086a13d06c1ca12994 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Fri, 6 Sep 2019 20:59:11 +0300 Subject: [PATCH 13/25] Added timeout to tests, added logs --- .../analyzers/communication_analyzer.py | 23 +++- .../blackbox/gcp_machine_handlers.py | 1 + .../blackbox/monkey_island_client.py | 59 +++++----- envs/monkey_zoo/blackbox/test_blackbox.py | 101 ++++++++++++++---- 4 files changed, 134 insertions(+), 50 deletions(-) diff --git a/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py b/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py index e4638233f..a91850057 100644 --- a/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py +++ b/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py @@ -1,22 +1,41 @@ import json +LOG_INIT_MESSAGE = "Analysis didn't run." + class CommunicationAnalyzer(object): def __init__(self, island_client, machine_ips): self.island_client = island_client self.machine_ips = machine_ips + self.log = AnalyzerLog(self.__class__.__name__) def analyze_test_results(self): + self.log.clear() for machine_ip in self.machine_ips: if not self.did_monkey_communicate_back(machine_ip): + self.log.add_entry("Monkey from {} didn't communicate back".format(machine_ip)) return False - print("Monkey from {} communicated back".format(machine_ip)) + self.log.add_entry("Monkey from {} communicated back".format(machine_ip)) return True def did_monkey_communicate_back(self, machine_ip): query = json.dumps({'ip_addresses': {'$elemMatch': {'$eq': machine_ip}}}) - response = self.island_client.send_get_request("api/test/monkey", {'find_query': query}) + response = self.island_client.request_get("api/test/monkey", {'find_query': query}) return len(json.loads(response.content)['results']) > 0 +class AnalyzerLog(object): + + def __init__(self, analyzer_name): + self.contents = LOG_INIT_MESSAGE + self.name = analyzer_name + + def clear(self): + self.contents = "" + + def add_entry(self, message): + self.contents = "{}\n{}".format(self.contents, message) + + def get_contents(self): + return "{}: {}\n".format(self.name, self.contents) diff --git a/envs/monkey_zoo/blackbox/gcp_machine_handlers.py b/envs/monkey_zoo/blackbox/gcp_machine_handlers.py index 4937191ed..3d6e75bf4 100644 --- a/envs/monkey_zoo/blackbox/gcp_machine_handlers.py +++ b/envs/monkey_zoo/blackbox/gcp_machine_handlers.py @@ -22,6 +22,7 @@ class GCPHandler(object): print("GCP Handler failed to initialize: %s." % e) def start_machines(self, machine_list): + print("Setting up all GCP machines...") try: subprocess.call((GCPHandler.MACHINE_STARTING_COMMAND % (machine_list, self.zone)), shell=True) print("GCP machines successfully started.") diff --git a/envs/monkey_zoo/blackbox/monkey_island_client.py b/envs/monkey_zoo/blackbox/monkey_island_client.py index 662ad71b8..a003f4d90 100644 --- a/envs/monkey_zoo/blackbox/monkey_island_client.py +++ b/envs/monkey_zoo/blackbox/monkey_island_client.py @@ -10,35 +10,31 @@ NO_AUTH_CREDS = '55e97c9dcfd22b8079189ddaeea9bce8125887e3237b800c6176c9afa80d206 class MonkeyIslandClient(object): def __init__(self, server_address): self.addr = "https://{IP}/".format(IP=server_address) - self.token = self.get_jwt_token_from_server() + self.token = self.get_jwt_from_server() - def get_jwt_token_from_server(self): - resp = requests.post(self.addr + "api/auth", json={"username": NO_AUTH_CREDS, "password": NO_AUTH_CREDS}, + def get_jwt_from_server(self): + resp = requests.post(self.addr + "api/auth", + json={"username": NO_AUTH_CREDS, "password": NO_AUTH_CREDS}, verify=False) return resp.json()["access_token"] - def request_get(self, url): - return requests.get( - self.addr + url, - headers={"Authorization": "JWT " + self.token}, - verify=False - ) + def request_get(self, url, data=None): + return requests.get(self.addr + url, + headers={"Authorization": "JWT " + self.token}, + params=data, + verify=False) def request_post(self, url, data): - return requests.post( - self.addr + url, - data=data, - headers={"Authorization": "JWT " + self.token}, - verify=False - ) + return requests.post(self.addr + url, + data=data, + headers={"Authorization": "JWT " + self.token}, + verify=False) - def request_json(self, url, dict_data): - return requests.post( - self.addr + url, - json=dict_data, - headers={"Authorization": "JWT " + self.token}, - verify=False - ) + def request_post_json(self, url, dict_data): + return requests.post(self.addr + url, + json=dict_data, + headers={"Authorization": "JWT " + self.token}, + verify=False) def get_api_status(self): return self.request_get("api") @@ -47,12 +43,15 @@ class MonkeyIslandClient(object): _ = self.request_post("api/configuration/island", data=config_contents) def run_monkey_local(self): - resp = self.request_json("api/local-monkey", dict_data={"action": "run"}) - print(resp.text) + if self.request_post_json("api/local-monkey", dict_data={"action": "run"}).ok: + print("Running the monkey.") + else: + print("Failed to run the monkey.") + assert False - def send_get_request(self, endpoint, data): - resp = requests.get(self.addr + endpoint, - headers={"Authorization": "JWT " + self.token}, - params=data, - verify=False) - return resp + def reset_env(self): + if self.request_get("api", {"action": "reset"}).ok: + print("Resetting environment after the test.") + else: + print("Failed to reset the environment.") + assert False diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index 5ef7e16f5..a8b31f4c5 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -1,41 +1,106 @@ import unittest +from time import sleep, time import pytest from envs.monkey_zoo.blackbox.monkey_island_client import MonkeyIslandClient from envs.monkey_zoo.blackbox.analyzers.communication_analyzer import CommunicationAnalyzer from envs.monkey_zoo.blackbox.island_config_parser import IslandConfigParser +from envs.monkey_zoo.blackbox.gcp_machine_handlers import GCPHandler -def generic_blackbox_test_case(client, raw_config, analyzers): - client.import_config(raw_config) - # client.run_monkey_local() - for analyzer in analyzers: - assert analyzer.analyze_test_results() +MACHINE_BOOT_TIME_SECONDS = 20 +TEST_TIME_SECONDS = 70 +DELAY_BETWEEN_TESTS = 1 + + +class BlackBoxTest(object): + + def __init__(self, name, island_client, island_config, analyzers, timeout=TEST_TIME_SECONDS): + self.name = name + self.island_client = island_client + self.island_config = island_config + self.analyzers = analyzers + self.timeout = timeout + + def run(self): + self.island_client.import_config(self.island_config) + self.island_client.run_monkey_local() + self.test_until_timeout() + self.island_client.reset_env() + + def test_until_timeout(self): + timer = TestTimer(self.timeout) + while not timer.timed_out(): + if self.analyzers_pass(): + self.log_success(timer) + return + sleep(DELAY_BETWEEN_TESTS) + self.log_failure(timer) + assert False + + def log_success(self, timer): + print(self.get_analyzer_logs()) + print("{} test passed, time taken: {:.1f} seconds.".format(self.name, timer.get_time_taken())) + + def log_failure(self, timer): + print(self.get_analyzer_logs()) + print("{} test failed because of timeout. Time taken: {:.1f} seconds.".format(self.name, + timer.get_time_taken())) + + def analyzers_pass(self): + for analyzer in self.analyzers: + if not analyzer.analyze_test_results(): + return False + return True + + def get_analyzer_logs(self): + log = "" + for analyzer in self.analyzers: + log += "\n"+analyzer.log.get_contents() + return log + + +class TestTimer(object): + def __init__(self, timeout): + self.timeout_time = TestTimer.get_timeout_time(timeout) + self.start_time = time() + + def timed_out(self): + return time() > self.timeout_time + + def get_time_taken(self): + return time() - self.start_time + + @staticmethod + def get_timeout_time(timeout): + return time() + timeout @pytest.mark.usefixtures("island") # noinspection PyUnresolvedReferences class TestMonkeyBlackbox(unittest.TestCase): - @classmethod - def setUpClass(cls): - # GCPHandler().start_machines("elastic-4") - print("Setting up all GCP machines...") - @classmethod - def tearDownClass(cls): - # GCPHandler().stop_machines("elastic-4") + def setUp(self): + self.GCPHandler = GCPHandler() + self.island_client = MonkeyIslandClient(self.island) + self.GCPHandler.start_machines("sshkeys-11 sshkeys-12") + TestMonkeyBlackbox.wait_for_machine_boot() + + def tearDown(self): + self.GCPHandler.stop_machines("sshkeys-11 sshkeys-12") print("Killing all GCP machines...") def test_server_online(self): - client = MonkeyIslandClient(self.island) - assert client.get_api_status() is not None + assert self.island_client.get_api_status() is not None def test_ssh_exec(self): conf_file_name = 'SSH.conf' - client = MonkeyIslandClient(self.island) config_parser = IslandConfigParser(conf_file_name) - analyzer = CommunicationAnalyzer(client, config_parser.get_ips_of_targets()) - generic_blackbox_test_case(client, config_parser.config_raw, [analyzer]) - + analyzer = CommunicationAnalyzer(self.island_client, config_parser.get_ips_of_targets()) + BlackBoxTest("SSH test", self.island_client, config_parser.config_raw, [analyzer]).run() + @staticmethod + def wait_for_machine_boot(time=MACHINE_BOOT_TIME_SECONDS): + print("Waiting for machines to fully boot up({:.0f} seconds).".format(time)) + sleep(time) From 36b6752827a2dcc5266e4b90152523b17e3f955e Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Wed, 11 Sep 2019 12:39:28 +0300 Subject: [PATCH 14/25] Refactored to run series of tests, improved configurations, file structure --- envs/monkey_zoo/blackbox/conftest.py | 4 +- .../blackbox/island_configs/ELASTIC.conf | 6 +- .../blackbox/island_configs/HADOOP.conf | 4 +- .../blackbox/island_configs/MSSQL.conf | 4 +- .../blackbox/island_configs/SHELLSHOCK.conf | 4 +- .../blackbox/island_configs/SMB_MIMIKATZ.conf | 9 +- .../blackbox/island_configs/SSH.conf | 19 +- .../blackbox/island_configs/STRUTS2.conf | 4 +- .../blackbox/island_configs/WEBLOGIC.conf | 4 +- .../blackbox/island_configs/WMI_MIMIKATZ.conf | 8 +- envs/monkey_zoo/blackbox/test_blackbox.py | 167 ++++++++---------- envs/monkey_zoo/blackbox/tests/__init__.py | 0 envs/monkey_zoo/blackbox/tests/basic_test.py | 55 ++++++ envs/monkey_zoo/blackbox/utils/__init__.py | 0 .../{ => utils}/gcp_machine_handlers.py | 0 .../{ => utils}/island_config_parser.py | 4 +- .../{ => utils}/monkey_island_client.py | 23 ++- envs/monkey_zoo/blackbox/utils/test_timer.py | 17 ++ 18 files changed, 195 insertions(+), 137 deletions(-) create mode 100644 envs/monkey_zoo/blackbox/tests/__init__.py create mode 100644 envs/monkey_zoo/blackbox/tests/basic_test.py create mode 100644 envs/monkey_zoo/blackbox/utils/__init__.py rename envs/monkey_zoo/blackbox/{ => utils}/gcp_machine_handlers.py (100%) rename envs/monkey_zoo/blackbox/{ => utils}/island_config_parser.py (70%) rename envs/monkey_zoo/blackbox/{ => utils}/monkey_island_client.py (71%) create mode 100644 envs/monkey_zoo/blackbox/utils/test_timer.py diff --git a/envs/monkey_zoo/blackbox/conftest.py b/envs/monkey_zoo/blackbox/conftest.py index ccbbe694a..13aabf5b6 100644 --- a/envs/monkey_zoo/blackbox/conftest.py +++ b/envs/monkey_zoo/blackbox/conftest.py @@ -6,6 +6,6 @@ def pytest_addoption(parser): help="Specify the Monkey Island address (host+port).") -@pytest.fixture +@pytest.fixture(scope='module') def island(request): - request.cls.island = request.config.getoption("--island") + return request.config.getoption("--island") diff --git a/envs/monkey_zoo/blackbox/island_configs/ELASTIC.conf b/envs/monkey_zoo/blackbox/island_configs/ELASTIC.conf index 4bf0af990..fb8a5a4de 100644 --- a/envs/monkey_zoo/blackbox/island_configs/ELASTIC.conf +++ b/envs/monkey_zoo/blackbox/island_configs/ELASTIC.conf @@ -21,7 +21,7 @@ "general": { "blocked_ips": [], "depth": 2, - "local_network_scan": true, + "local_network_scan": false, "subnet_scan_list": [ "10.2.2.4", "10.2.2.5" @@ -107,7 +107,7 @@ "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 60, + "keep_tunnel_open_time": 50, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, @@ -181,4 +181,4 @@ ] } } -} \ No newline at end of file +} diff --git a/envs/monkey_zoo/blackbox/island_configs/HADOOP.conf b/envs/monkey_zoo/blackbox/island_configs/HADOOP.conf index f61afc9ae..26508d3f4 100644 --- a/envs/monkey_zoo/blackbox/island_configs/HADOOP.conf +++ b/envs/monkey_zoo/blackbox/island_configs/HADOOP.conf @@ -118,7 +118,7 @@ "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 60, + "keep_tunnel_open_time": 50, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, @@ -192,4 +192,4 @@ ] } } -} \ No newline at end of file +} diff --git a/envs/monkey_zoo/blackbox/island_configs/MSSQL.conf b/envs/monkey_zoo/blackbox/island_configs/MSSQL.conf index 111cd304f..621a86950 100644 --- a/envs/monkey_zoo/blackbox/island_configs/MSSQL.conf +++ b/envs/monkey_zoo/blackbox/island_configs/MSSQL.conf @@ -106,7 +106,7 @@ "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 60, + "keep_tunnel_open_time": 50, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, @@ -180,4 +180,4 @@ ] } } -} \ No newline at end of file +} diff --git a/envs/monkey_zoo/blackbox/island_configs/SHELLSHOCK.conf b/envs/monkey_zoo/blackbox/island_configs/SHELLSHOCK.conf index 0ca343ae0..19d0ba17b 100644 --- a/envs/monkey_zoo/blackbox/island_configs/SHELLSHOCK.conf +++ b/envs/monkey_zoo/blackbox/island_configs/SHELLSHOCK.conf @@ -106,7 +106,7 @@ "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 60, + "keep_tunnel_open_time": 50, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, @@ -180,4 +180,4 @@ ] } } -} \ No newline at end of file +} diff --git a/envs/monkey_zoo/blackbox/island_configs/SMB_MIMIKATZ.conf b/envs/monkey_zoo/blackbox/island_configs/SMB_MIMIKATZ.conf index bfccc4d62..c3873c707 100644 --- a/envs/monkey_zoo/blackbox/island_configs/SMB_MIMIKATZ.conf +++ b/envs/monkey_zoo/blackbox/island_configs/SMB_MIMIKATZ.conf @@ -101,14 +101,11 @@ }, "exploits": { "exploit_lm_hash_list": [], - "exploit_ntlm_hash_list": [ - "5da0889ea2081aa79f6852294cba4a5e", - "5da0889ea2081aa79f6852294cba4a5e" - ], + "exploit_ntlm_hash_list": [], "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 60, + "keep_tunnel_open_time": 50, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, @@ -182,4 +179,4 @@ ] } } -} \ No newline at end of file +} diff --git a/envs/monkey_zoo/blackbox/island_configs/SSH.conf b/envs/monkey_zoo/blackbox/island_configs/SSH.conf index da4325f85..9beae4036 100644 --- a/envs/monkey_zoo/blackbox/island_configs/SSH.conf +++ b/envs/monkey_zoo/blackbox/island_configs/SSH.conf @@ -112,23 +112,10 @@ "exploits": { "exploit_lm_hash_list": [], "exploit_ntlm_hash_list": [], - "exploit_ssh_keys": [ - { - "ip": "10.2.2.41", - "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAyH0k1LOILDTVli5NlqcvRdoRc2aMn5I5ZhJsnBNuzB28D6Fd\nAEbjDn/v+dPK58L4WGoGMpHqk47mNDgdTIkfP5BBgbuQpBUmrsCZn8QVRpqZ3ESC\nXsnMrOjrYRqTelquGWR9xJvIJwNz3UbME2c8SYOPc3tHsINyn8Tt2ssA8L9KjcTe\n6CzNpbCNbZ6Q3o7/isYP79ogiFY+VHK3rtBY17aG9bDx5vce8RoIr463u/+a+jYX\nPuzZgndTtO3EPwq4Ti1pydpuJo9PYh1iY6RP3XPMYNwpoKToYzyESeqqwolmz+nh\nEh/rQtuwwW7043IM+62w9UPkHWv28pqDZxBxhwIDAQABAoIBAGA1/ei8xwo/yIer\nbLxxOnRQ87LncXBaIYVkLg6wHKmDU25Ex3aMjgW1S5oeEu8pVzhGmPbHo0RwfPRu\nQVErNH2yYl05f23eYJPYBWDwHi2ln1Re5BlMyhXoKJyOvlsnDQlOejRRdbmTJJT5\nlpFxJzM4GS0X6g1A507YmDQ42xisOkmL/Wsv/t9/GiE9P6h0I1bNmXzSy8sDZwea\nNDe09U+rfuIkh2tO+nEzWs13AG3CxV9YlK4vMK7A0KiWF8LPvrbBegEm5VG+qrJ2\nsxoDkCBc5DV6QRyLU1SIyDIRIR2J0gTgfLDSbqNp0qm+Zby2o3V/q26bvrWWwP9a\nU/W2vJECgYEA5jK52pUMmriCiWNgQOiyOGx5OfHo6gRomiiiALivaMhNN3mm8CFI\nuIXMjU1V0BoHXCW8ciMOAeXl72rX/XVC+/E3GJQFCtBHJQ6tPNOOnWcxR/Ldwvxd\nsBz8Wx50MlxvbrxqtzTn+VmVnExKskwsZGI/GDPotPo7QKcBJUsGfhsCgYEA3vXx\ncyG805RsJH/J54cg+cHW5xDn6YNuHwbVdB4FWfi184oDDxtPT84XF1JA3dN3gwJF\nSfO1kNwpNK0C58evJA+6rZfUps/HOcQqFPvzCUhkLeZD5QgaOTQZBKndXYgeXkJD\ntpN+kjhCdxWN40N6FAMtLUYTbaQdTUHSBuXzoQUCgYEAgwXgTw+DCxV2ByjvAkLw\nHblwDpEoVvqHZyc1fl+gR22qtaaiZA8tywks8khQTZBjHAnGhth5Ao+OHoWbxoHV\nzHzxNSYa8Jq3w9nktLhddi3kGOWdX3ww/yqgYGSnEnsWWdsYioqsdnqM81dhNLay\nlbht3SK+kzPSQexMdKONYH0CgYAS1lKk+Ie8lICigM1tK0SE9XSTpyEA4KLQKkKk\ngdjP5ixxPArQHu2Pf4kB5mgmlbQ2NF3oRpfjekZc9fUV4hARCucpvXcw9MMPRVyM\n01CQSzZzjk3ULuAQTy+B7lwOh+6Q5iZUaZe7ANfUudR4C/5nbHFHrvD7RW9YVKRL\nAuiXhQKBgDMFeZRfu/dhTdVQ9XZigOWvkeXYxxoloiIHIg3ByZwEAlH/RnlA0M1Z\nOaLt/Q1KNh2UDKkstfOAJ1FdqLm3JU0Hqx/D8dpvTUQBkqoMf8U1WQC2WVmlpmUv\ndrIj1d5/r2N1Cxorx0IbVWsW7WPVM/lVyBU7+2QsKoI5YIervsJY\n-----END RSA PRIVATE KEY-----\n", - "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIfSTUs4gsNNWWLk2Wpy9F2hFzZoyfkjlmEmycE27MHbwPoV0ARuMOf+/508rnwvhYagYykeqTjuY0OB1MiR8/kEGBu5CkFSauwJmfxBVGmpncRIJeycys6OthGpN6Wq4ZZH3Em8gnA3PdRswTZzxJg49ze0ewg3KfxO3aywDwv0qNxN7oLM2lsI1tnpDejv+Kxg/v2iCIVj5Ucreu0FjXtob1sPHm9x7xGgivjre7/5r6Nhc+7NmCd1O07cQ/CrhOLWnJ2m4mj09iHWJjpE/dc8xg3CmgpOhjPIRJ6qrCiWbP6eESH+tC27DBbvTjcgz7rbD1Q+Qda/bymoNnEHGH m0nk3y@sshkeys-11\n", - "user": "m0nk3y" - }, - { - "ip": "10.2.2.42", - "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA5fmqwJV/NZOThZ0B0SXJ7jz+xp2zvVI+DR141JpEJGAm8xP8\nCMmDACkGVDZfwQQEWsmG6WHsRJnBTm1jawUbhgD8EGYNp9sj8G4oW6GvThzzlZvp\nABgtSyWtT6CLBoF7t3/wgFXfAaA33lTg/Ht+bXBMaAZiHyRlexPjmtfhu1Hw44cM\nBuxJwA31OqnO0OPKOh6wW0OWta9BsJnFBckEve1y2Bf2SOnFdlAEV9tNWwGt/AK8\nMAEpgwEZXISrqOucjn7YGEzfZ+Ygjq4/M3FGE31ttrTgERqAPchd1Cp6da6mlYtu\nzx35spV2kxf2ydYHYOOgvS8cCIIk7GIANZztmQIDAQABAoIBAQCAOcXQHUrRV5hw\nbkt+DuDZWd8AZRu7mqiIbX9aoy0NTyNIc0MaryjApR8nQy3+k7vN1wHHDNdMpKIY\nlXtSR4XCILhqeExy5AfU3cbY2HzDQ/c42rZ+W/ydIsPQWwZJOVb+yHITTE3MPUYJ\nTDAp9r1WTb/8XFrHXGbMyhkk0+vDoezj+FDS0YbFImt2iFgC7wgDjuoG5CnlW09/\n/r2bfH/qKKvs9sDwCypVqH5bki1VyQLRfdrCgPisBnhBAj8OBFN+IN5L3P+Zv5UI\nwyZA34RETijHb158vAtIfz2LT0Gin6CNGZY+QOOjM1hCevgrbLeD13Bc9Oog7367\nlm10eMKBAoGBAPUPrbpgA/rg77YrL7uBQhy13HtrRnxW4AjtDs/dEelXlF/Zdfi6\nzukVkb6PaYVPAOC58E21gOJNDYXUdwkbGrJSIDr6rfb9AeEnGIcyDPn36roLjGBn\nJO3Ikr4AhycjbQVVdvo4VY5baCtHNonbn4VFeb+ThszMOQWci4djPGWJAoGBAPA9\nmbboApqV/zoy4PAukFFWOUxb+3GxwcywlVYIuAk3DfM5zJuLgxV70KJ/Z6ppmTzF\n+uPkydTFQv/aLA3IiUioPijl2/l1HmspHpzQztdJaMHhFolKCB+X7wa7QlSFKKyE\ngT8dV8mPsW2HMoNv/yfVQ7lv2M9t4CKhzgssnFORAoGAbeqJXqYAQv+vJQM71ptE\nXwJHEWhtZgnFVNuXIC6lAQdSOqecHWMUuUD+bP2AM9Xaq/FaUlCNrXMoFJXWilQI\n5mClqi6T5stWk3lorAMMBPZo5ueVIAxDaQ/kmao89JYUKSdLRTINVduz3m2DjdPf\nOfSOhhoShTs4fEbZ4nDlPxkCgYEAhz1WM/YFyToZVIzhvbOowHD2jnrVYJp9i5n4\nZ1c/KsjYTIzEFugBoe1ydJeeJvuNLP4Sj4ny6Jknb1pFJHk4dzNm0qUbISICPrcG\nKacOWXlUxJfOlPic/BQOlc6Ct4vCauOo0nvVOH1wl0Tddcpta+INXu2MsrCa1UQa\n9oVld1ECgYADhllIDq3mkM4y58BSIOQ7uOKqbOgTyOjUCS2cFtYXtv6UY/OxFVxJ\n9soergMdd1uDOOwv96Yu9aNzgqjXFixb3Gyk+xh1viOpLrpbCUgg6j20IHcv8pwS\nhsp2wHDCuS8cKK9E8RJ3YYNgLh5uH1J+GhzSix1V8sizT0Y1UPOCDQ==\n-----END RSA PRIVATE KEY-----\n", - "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDl+arAlX81k5OFnQHRJcnuPP7GnbO9Uj4NHXjUmkQkYCbzE/wIyYMAKQZUNl/BBARayYbpYexEmcFObWNrBRuGAPwQZg2n2yPwbihboa9OHPOVm+kAGC1LJa1PoIsGgXu3f/CAVd8BoDfeVOD8e35tcExoBmIfJGV7E+Oa1+G7UfDjhwwG7EnADfU6qc7Q48o6HrBbQ5a1r0GwmcUFyQS97XLYF/ZI6cV2UARX201bAa38ArwwASmDARlchKuo65yOftgYTN9n5iCOrj8zcUYTfW22tOARGoA9yF3UKnp1rqaVi27PHfmylXaTF/bJ1gdg46C9LxwIgiTsYgA1nO2Z m0nk3y@sshkeys-12\n", - "user": "m0nk3y" - } - ] + "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 60, + "keep_tunnel_open_time": 50, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, @@ -202,4 +189,4 @@ ] } } -} \ No newline at end of file +} diff --git a/envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf b/envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf index d47becb64..469734d96 100644 --- a/envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf +++ b/envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf @@ -116,7 +116,7 @@ "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 60, + "keep_tunnel_open_time": 50, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, @@ -190,4 +190,4 @@ ] } } -} \ No newline at end of file +} diff --git a/envs/monkey_zoo/blackbox/island_configs/WEBLOGIC.conf b/envs/monkey_zoo/blackbox/island_configs/WEBLOGIC.conf index 50ad122e4..0c8ba6024 100644 --- a/envs/monkey_zoo/blackbox/island_configs/WEBLOGIC.conf +++ b/envs/monkey_zoo/blackbox/island_configs/WEBLOGIC.conf @@ -107,7 +107,7 @@ "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 60, + "keep_tunnel_open_time": 50, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, @@ -181,4 +181,4 @@ ] } } -} \ No newline at end of file +} diff --git a/envs/monkey_zoo/blackbox/island_configs/WMI_MIMIKATZ.conf b/envs/monkey_zoo/blackbox/island_configs/WMI_MIMIKATZ.conf index 3e3b8c103..f33bcd3de 100644 --- a/envs/monkey_zoo/blackbox/island_configs/WMI_MIMIKATZ.conf +++ b/envs/monkey_zoo/blackbox/island_configs/WMI_MIMIKATZ.conf @@ -109,13 +109,11 @@ }, "exploits": { "exploit_lm_hash_list": [], - "exploit_ntlm_hash_list": [ - "5da0889ea2081aa79f6852294cba4a5e" - ], + "exploit_ntlm_hash_list": [], "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 60, + "keep_tunnel_open_time": 50, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, @@ -189,4 +187,4 @@ ] } } -} \ No newline at end of file +} diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index a8b31f4c5..dc7032299 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -1,106 +1,89 @@ -import unittest -from time import sleep, time +from time import sleep import pytest -from envs.monkey_zoo.blackbox.monkey_island_client import MonkeyIslandClient +from envs.monkey_zoo.blackbox.utils.monkey_island_client import MonkeyIslandClient from envs.monkey_zoo.blackbox.analyzers.communication_analyzer import CommunicationAnalyzer -from envs.monkey_zoo.blackbox.island_config_parser import IslandConfigParser -from envs.monkey_zoo.blackbox.gcp_machine_handlers import GCPHandler +from envs.monkey_zoo.blackbox.utils.island_config_parser import IslandConfigParser +from envs.monkey_zoo.blackbox.utils import gcp_machine_handlers +from envs.monkey_zoo.blackbox.tests.basic_test import BasicTest + +DEFAULT_TIMEOUT_SECONDS = 4 * 60 # 4 minutes +DELAY_BETWEEN_TESTS = 10 +GCP_TEST_MACHINE_LIST = ['sshkeys-11', 'sshkeys-12', 'elastic-4', 'elastic-5', 'haddop-2-v3', 'hadoop-3', 'mssql-16', + 'mimikatz-14', 'mimikatz-15', 'final-test-struts2-23', 'final-test-struts2-24', + 'tunneling-9', 'tunneling-10', 'tunneling-11', 'weblogic-18', 'weblogic-19', 'shellshock-8'] -MACHINE_BOOT_TIME_SECONDS = 20 -TEST_TIME_SECONDS = 70 -DELAY_BETWEEN_TESTS = 1 +@pytest.fixture(autouse=True, scope='session') +def GCPHandler(request): + GCPHandler = gcp_machine_handlers.GCPHandler() + #GCPHandler.start_machines(" ".join(GCP_TEST_MACHINE_LIST)) + + def fin(): + pass + # GCPHandler.stop_machines(" ".join(GCP_TEST_MACHINE_LIST)) + + request.addfinalizer(fin) -class BlackBoxTest(object): - - def __init__(self, name, island_client, island_config, analyzers, timeout=TEST_TIME_SECONDS): - self.name = name - self.island_client = island_client - self.island_config = island_config - self.analyzers = analyzers - self.timeout = timeout - - def run(self): - self.island_client.import_config(self.island_config) - self.island_client.run_monkey_local() - self.test_until_timeout() - self.island_client.reset_env() - - def test_until_timeout(self): - timer = TestTimer(self.timeout) - while not timer.timed_out(): - if self.analyzers_pass(): - self.log_success(timer) - return - sleep(DELAY_BETWEEN_TESTS) - self.log_failure(timer) - assert False - - def log_success(self, timer): - print(self.get_analyzer_logs()) - print("{} test passed, time taken: {:.1f} seconds.".format(self.name, timer.get_time_taken())) - - def log_failure(self, timer): - print(self.get_analyzer_logs()) - print("{} test failed because of timeout. Time taken: {:.1f} seconds.".format(self.name, - timer.get_time_taken())) - - def analyzers_pass(self): - for analyzer in self.analyzers: - if not analyzer.analyze_test_results(): - return False - return True - - def get_analyzer_logs(self): - log = "" - for analyzer in self.analyzers: - log += "\n"+analyzer.log.get_contents() - return log +@pytest.fixture(scope='class') +def island_client(island): + island_client_object = MonkeyIslandClient(island) + yield island_client_object -class TestTimer(object): - def __init__(self, timeout): - self.timeout_time = TestTimer.get_timeout_time(timeout) - self.start_time = time() - - def timed_out(self): - return time() > self.timeout_time - - def get_time_taken(self): - return time() - self.start_time - - @staticmethod - def get_timeout_time(timeout): - return time() + timeout - - -@pytest.mark.usefixtures("island") +@pytest.mark.usefixtures('island_client') # noinspection PyUnresolvedReferences -class TestMonkeyBlackbox(unittest.TestCase): +class TestMonkeyBlackbox(object): - def setUp(self): - self.GCPHandler = GCPHandler() - self.island_client = MonkeyIslandClient(self.island) - self.GCPHandler.start_machines("sshkeys-11 sshkeys-12") - TestMonkeyBlackbox.wait_for_machine_boot() - - def tearDown(self): - self.GCPHandler.stop_machines("sshkeys-11 sshkeys-12") - print("Killing all GCP machines...") - - def test_server_online(self): - assert self.island_client.get_api_status() is not None - - def test_ssh_exec(self): - conf_file_name = 'SSH.conf' - config_parser = IslandConfigParser(conf_file_name) - analyzer = CommunicationAnalyzer(self.island_client, config_parser.get_ips_of_targets()) - BlackBoxTest("SSH test", self.island_client, config_parser.config_raw, [analyzer]).run() + def run_basic_test(self, island_client, conf_filename, test_name, timeout_in_seconds=DEFAULT_TIMEOUT_SECONDS): + TestMonkeyBlackbox.wait_between_tests() + config_parser = IslandConfigParser(conf_filename) + analyzer = CommunicationAnalyzer(island_client, config_parser.get_ips_of_targets()) + BasicTest(test_name, + island_client, + config_parser.config_raw, + [analyzer], + timeout_in_seconds).run() @staticmethod - def wait_for_machine_boot(time=MACHINE_BOOT_TIME_SECONDS): - print("Waiting for machines to fully boot up({:.0f} seconds).".format(time)) - sleep(time) + def wait_between_tests(): + print("Waiting for ({:.0f} seconds) for old monkey's to die or GCP machines to boot up.".format(DELAY_BETWEEN_TESTS)) + sleep(DELAY_BETWEEN_TESTS) + + """ + def test_server_online(self, island_client): + assert island_client.get_api_status() is not None + + def test_ssh_exploiter(self, island_client): + self.run_basic_test(island_client, "SSH.conf", "SSH exploiter and keys") + + def test_hadoop_exploiter(self, island_client): + self.run_basic_test(island_client, "HADOOP.conf", "Hadoop exploiter") + + def test_mssql_exploiter(self, island_client): + self.run_basic_test(island_client, "MSSQL.conf", "MSSQL exploiter") + """ + def test_smb_and_mimikatz_exploiters(self, island_client): + self.run_basic_test(island_client, "SMB_MIMIKATZ.conf", "SMB exploiter, mimikatz") + """ + def test_elastic_exploiter(self, island_client): + self.run_basic_test(island_client, "ELASTIC.conf", "Elastic exploiter", 180) + + + def test_struts_exploiter(self, island_client): + self.run_basic_test(island_client, "STRUTS2.conf", "Strtuts2 exploiter") + + def test_weblogic_exploiter(self, island_client): + self.run_basic_test(island_client, "WEBLOGIC.conf", "Weblogic exploiter") + + def test_shellshock_exploiter(self, island_client): + self.run_basic_test(island_client, "SHELLSHOCK.conf", "Shellschock exploiter") + + def test_tunneling(self, island_client): + self.run_basic_test(island_client, "TUNNELING.conf", "Tunneling exploiter") + + def test_wmi_exploiter(self, island_client): + self.run_basic_test(island_client, "WMI_MIMIKATZ.conf", "WMI exploiter, mimikatz") + """ diff --git a/envs/monkey_zoo/blackbox/tests/__init__.py b/envs/monkey_zoo/blackbox/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/envs/monkey_zoo/blackbox/tests/basic_test.py b/envs/monkey_zoo/blackbox/tests/basic_test.py new file mode 100644 index 000000000..f21feccb7 --- /dev/null +++ b/envs/monkey_zoo/blackbox/tests/basic_test.py @@ -0,0 +1,55 @@ +from time import sleep + +from envs.monkey_zoo.blackbox.utils.test_timer import TestTimer + +DELAY_BETWEEN_ANALYSIS = 1 + + +class BasicTest(object): + + def __init__(self, name, island_client, island_config, analyzers, timeout): + self.name = name + self.island_client = island_client + self.island_config = island_config + self.analyzers = analyzers + self.timeout = timeout + + def run(self): + self.island_client.import_config(self.island_config) + try: + self.island_client.run_monkey_local() + self.test_until_timeout() + finally: + self.island_client.kill_all_monkeys() + self.island_client.reset_env() + + def test_until_timeout(self): + timer = TestTimer(self.timeout) + while not timer.timed_out(): + if self.all_analyzers_pass(): + self.log_success(timer) + return + sleep(DELAY_BETWEEN_ANALYSIS) + self.log_failure(timer) + assert False + + def log_success(self, timer): + print(self.get_analyzer_logs()) + print("{} test passed, time taken: {:.1f} seconds.".format(self.name, timer.get_time_taken())) + + def log_failure(self, timer): + print(self.get_analyzer_logs()) + print("{} test failed because of timeout. Time taken: {:.1f} seconds.".format(self.name, + timer.get_time_taken())) + + def all_analyzers_pass(self): + for analyzer in self.analyzers: + if not analyzer.analyze_test_results(): + return False + return True + + def get_analyzer_logs(self): + log = "" + for analyzer in self.analyzers: + log += "\n"+analyzer.log.get_contents() + return log diff --git a/envs/monkey_zoo/blackbox/utils/__init__.py b/envs/monkey_zoo/blackbox/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/envs/monkey_zoo/blackbox/gcp_machine_handlers.py b/envs/monkey_zoo/blackbox/utils/gcp_machine_handlers.py similarity index 100% rename from envs/monkey_zoo/blackbox/gcp_machine_handlers.py rename to envs/monkey_zoo/blackbox/utils/gcp_machine_handlers.py diff --git a/envs/monkey_zoo/blackbox/island_config_parser.py b/envs/monkey_zoo/blackbox/utils/island_config_parser.py similarity index 70% rename from envs/monkey_zoo/blackbox/island_config_parser.py rename to envs/monkey_zoo/blackbox/utils/island_config_parser.py index 63c98cb75..948b58310 100644 --- a/envs/monkey_zoo/blackbox/island_config_parser.py +++ b/envs/monkey_zoo/blackbox/utils/island_config_parser.py @@ -13,4 +13,6 @@ class IslandConfigParser(object): @staticmethod def get_conf_file_path(conf_file_name): - return os.path.join(os.path.dirname(os.path.abspath(__file__)), "island_configs", conf_file_name) + return os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), + "island_configs", + conf_file_name) diff --git a/envs/monkey_zoo/blackbox/monkey_island_client.py b/envs/monkey_zoo/blackbox/utils/monkey_island_client.py similarity index 71% rename from envs/monkey_zoo/blackbox/monkey_island_client.py rename to envs/monkey_zoo/blackbox/utils/monkey_island_client.py index a003f4d90..6c4cd1258 100644 --- a/envs/monkey_zoo/blackbox/monkey_island_client.py +++ b/envs/monkey_zoo/blackbox/utils/monkey_island_client.py @@ -10,7 +10,14 @@ NO_AUTH_CREDS = '55e97c9dcfd22b8079189ddaeea9bce8125887e3237b800c6176c9afa80d206 class MonkeyIslandClient(object): def __init__(self, server_address): self.addr = "https://{IP}/".format(IP=server_address) - self.token = self.get_jwt_from_server() + self.token = self.try_get_jwt_from_server() + + def try_get_jwt_from_server(self): + try: + return self.get_jwt_from_server() + except requests.ConnectionError: + print("Unable to connect to island, aborting!") + assert False def get_jwt_from_server(self): resp = requests.post(self.addr + "api/auth", @@ -43,12 +50,24 @@ class MonkeyIslandClient(object): _ = self.request_post("api/configuration/island", data=config_contents) def run_monkey_local(self): - if self.request_post_json("api/local-monkey", dict_data={"action": "run"}).ok: + response = self.request_post_json("api/local-monkey", dict_data={"action": "run"}) + if MonkeyIslandClient.monkey_ran_successfully(response): print("Running the monkey.") else: print("Failed to run the monkey.") assert False + @staticmethod + def monkey_ran_successfully(response): + return response.ok and json.loads(response.content)['is_running'] + + def kill_all_monkeys(self): + if self.request_get("api", {"action": "killall"}).ok: + print("Killing all monkeys after the test.") + else: + print("Failed to kill all monkeys.") + assert False + def reset_env(self): if self.request_get("api", {"action": "reset"}).ok: print("Resetting environment after the test.") diff --git a/envs/monkey_zoo/blackbox/utils/test_timer.py b/envs/monkey_zoo/blackbox/utils/test_timer.py new file mode 100644 index 000000000..c403d8a35 --- /dev/null +++ b/envs/monkey_zoo/blackbox/utils/test_timer.py @@ -0,0 +1,17 @@ +from time import time + + +class TestTimer(object): + def __init__(self, timeout): + self.timeout_time = TestTimer.get_timeout_time(timeout) + self.start_time = time() + + def timed_out(self): + return time() > self.timeout_time + + def get_time_taken(self): + return time() - self.start_time + + @staticmethod + def get_timeout_time(timeout): + return time() + timeout From a17305a324f77cdbaeea6d0e733551e1774d8d30 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Wed, 11 Sep 2019 15:44:57 +0300 Subject: [PATCH 15/25] More improvements on the configs --- .../blackbox/island_configs/ELASTIC.conf | 2 +- .../blackbox/island_configs/HADOOP.conf | 2 +- .../blackbox/island_configs/MSSQL.conf | 2 +- .../blackbox/island_configs/SHELLSHOCK.conf | 2 +- .../blackbox/island_configs/SMB_MIMIKATZ.conf | 4 ++-- .../monkey_zoo/blackbox/island_configs/SSH.conf | 2 +- .../blackbox/island_configs/STRUTS2.conf | 2 +- .../blackbox/island_configs/TUNNELING.conf | 4 ++-- .../blackbox/island_configs/WEBLOGIC.conf | 2 +- .../blackbox/island_configs/WMI_MIMIKATZ.conf | 4 ++-- envs/monkey_zoo/blackbox/test_blackbox.py | 17 +++++++++-------- envs/monkey_zoo/blackbox/tests/basic_test.py | 1 - .../blackbox/utils/monkey_island_client.py | 11 +++++++++++ 13 files changed, 33 insertions(+), 22 deletions(-) diff --git a/envs/monkey_zoo/blackbox/island_configs/ELASTIC.conf b/envs/monkey_zoo/blackbox/island_configs/ELASTIC.conf index fb8a5a4de..0a81ea700 100644 --- a/envs/monkey_zoo/blackbox/island_configs/ELASTIC.conf +++ b/envs/monkey_zoo/blackbox/island_configs/ELASTIC.conf @@ -107,7 +107,7 @@ "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 50, + "keep_tunnel_open_time": 1, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, diff --git a/envs/monkey_zoo/blackbox/island_configs/HADOOP.conf b/envs/monkey_zoo/blackbox/island_configs/HADOOP.conf index 26508d3f4..be97bbc26 100644 --- a/envs/monkey_zoo/blackbox/island_configs/HADOOP.conf +++ b/envs/monkey_zoo/blackbox/island_configs/HADOOP.conf @@ -118,7 +118,7 @@ "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 50, + "keep_tunnel_open_time": 1, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, diff --git a/envs/monkey_zoo/blackbox/island_configs/MSSQL.conf b/envs/monkey_zoo/blackbox/island_configs/MSSQL.conf index 621a86950..dc3332ed6 100644 --- a/envs/monkey_zoo/blackbox/island_configs/MSSQL.conf +++ b/envs/monkey_zoo/blackbox/island_configs/MSSQL.conf @@ -106,7 +106,7 @@ "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 50, + "keep_tunnel_open_time": 1, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, diff --git a/envs/monkey_zoo/blackbox/island_configs/SHELLSHOCK.conf b/envs/monkey_zoo/blackbox/island_configs/SHELLSHOCK.conf index 19d0ba17b..7fd857e65 100644 --- a/envs/monkey_zoo/blackbox/island_configs/SHELLSHOCK.conf +++ b/envs/monkey_zoo/blackbox/island_configs/SHELLSHOCK.conf @@ -106,7 +106,7 @@ "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 50, + "keep_tunnel_open_time": 1, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, diff --git a/envs/monkey_zoo/blackbox/island_configs/SMB_MIMIKATZ.conf b/envs/monkey_zoo/blackbox/island_configs/SMB_MIMIKATZ.conf index c3873c707..b5001025f 100644 --- a/envs/monkey_zoo/blackbox/island_configs/SMB_MIMIKATZ.conf +++ b/envs/monkey_zoo/blackbox/island_configs/SMB_MIMIKATZ.conf @@ -105,7 +105,7 @@ "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 50, + "keep_tunnel_open_time": 1, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, @@ -136,7 +136,7 @@ "post_breach_actions": [] }, "life_cycle": { - "max_iterations": 2, + "max_iterations": 1, "retry_failed_explotation": true, "timeout_between_iterations": 100, "victims_max_exploit": 7, diff --git a/envs/monkey_zoo/blackbox/island_configs/SSH.conf b/envs/monkey_zoo/blackbox/island_configs/SSH.conf index 9beae4036..e96894111 100644 --- a/envs/monkey_zoo/blackbox/island_configs/SSH.conf +++ b/envs/monkey_zoo/blackbox/island_configs/SSH.conf @@ -115,7 +115,7 @@ "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 50, + "keep_tunnel_open_time": 1, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, diff --git a/envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf b/envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf index 469734d96..30bb135e4 100644 --- a/envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf +++ b/envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf @@ -116,7 +116,7 @@ "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 50, + "keep_tunnel_open_time": 1, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, diff --git a/envs/monkey_zoo/blackbox/island_configs/TUNNELING.conf b/envs/monkey_zoo/blackbox/island_configs/TUNNELING.conf index 62dd40e30..a7e84f1b8 100644 --- a/envs/monkey_zoo/blackbox/island_configs/TUNNELING.conf +++ b/envs/monkey_zoo/blackbox/island_configs/TUNNELING.conf @@ -23,7 +23,7 @@ "depth": 3, "local_network_scan": false, "subnet_scan_list": [ - "10.2.2.39", + "10.2.2.32", "10.2.1.10", "10.2.0.11" ] @@ -191,4 +191,4 @@ ] } } -} \ No newline at end of file +} diff --git a/envs/monkey_zoo/blackbox/island_configs/WEBLOGIC.conf b/envs/monkey_zoo/blackbox/island_configs/WEBLOGIC.conf index 0c8ba6024..b86b2b566 100644 --- a/envs/monkey_zoo/blackbox/island_configs/WEBLOGIC.conf +++ b/envs/monkey_zoo/blackbox/island_configs/WEBLOGIC.conf @@ -107,7 +107,7 @@ "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 50, + "keep_tunnel_open_time": 1, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, diff --git a/envs/monkey_zoo/blackbox/island_configs/WMI_MIMIKATZ.conf b/envs/monkey_zoo/blackbox/island_configs/WMI_MIMIKATZ.conf index f33bcd3de..1498530d5 100644 --- a/envs/monkey_zoo/blackbox/island_configs/WMI_MIMIKATZ.conf +++ b/envs/monkey_zoo/blackbox/island_configs/WMI_MIMIKATZ.conf @@ -113,7 +113,7 @@ "exploit_ssh_keys": [] }, "general": { - "keep_tunnel_open_time": 50, + "keep_tunnel_open_time": 1, "monkey_dir_name": "monkey_dir", "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" }, @@ -144,7 +144,7 @@ "post_breach_actions": [] }, "life_cycle": { - "max_iterations": 2, + "max_iterations": 1, "retry_failed_explotation": true, "timeout_between_iterations": 100, "victims_max_exploit": 7, diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index dc7032299..1c747cb77 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -8,8 +8,8 @@ from envs.monkey_zoo.blackbox.utils.island_config_parser import IslandConfigPars from envs.monkey_zoo.blackbox.utils import gcp_machine_handlers from envs.monkey_zoo.blackbox.tests.basic_test import BasicTest -DEFAULT_TIMEOUT_SECONDS = 4 * 60 # 4 minutes -DELAY_BETWEEN_TESTS = 10 +DEFAULT_TIMEOUT_SECONDS = 3 * 60 +DELAY_BETWEEN_TESTS = 30 GCP_TEST_MACHINE_LIST = ['sshkeys-11', 'sshkeys-12', 'elastic-4', 'elastic-5', 'haddop-2-v3', 'hadoop-3', 'mssql-16', 'mimikatz-14', 'mimikatz-15', 'final-test-struts2-23', 'final-test-struts2-24', 'tunneling-9', 'tunneling-10', 'tunneling-11', 'weblogic-18', 'weblogic-19', 'shellshock-8'] @@ -52,7 +52,6 @@ class TestMonkeyBlackbox(object): print("Waiting for ({:.0f} seconds) for old monkey's to die or GCP machines to boot up.".format(DELAY_BETWEEN_TESTS)) sleep(DELAY_BETWEEN_TESTS) - """ def test_server_online(self, island_client): assert island_client.get_api_status() is not None @@ -62,15 +61,18 @@ class TestMonkeyBlackbox(object): def test_hadoop_exploiter(self, island_client): self.run_basic_test(island_client, "HADOOP.conf", "Hadoop exploiter") - def test_mssql_exploiter(self, island_client): - self.run_basic_test(island_client, "MSSQL.conf", "MSSQL exploiter") """ + def test_mssql_exploiter(self, island_client): + self.run_basic_test(island_client, "MSSQL.conf", "MSSQL exploiter") + """ + def test_smb_and_mimikatz_exploiters(self, island_client): self.run_basic_test(island_client, "SMB_MIMIKATZ.conf", "SMB exploiter, mimikatz") + """ def test_elastic_exploiter(self, island_client): - self.run_basic_test(island_client, "ELASTIC.conf", "Elastic exploiter", 180) - + self.run_basic_test(island_client, "ELASTIC.conf", "Elastic exploiter") + """ def test_struts_exploiter(self, island_client): self.run_basic_test(island_client, "STRUTS2.conf", "Strtuts2 exploiter") @@ -86,4 +88,3 @@ class TestMonkeyBlackbox(object): def test_wmi_exploiter(self, island_client): self.run_basic_test(island_client, "WMI_MIMIKATZ.conf", "WMI exploiter, mimikatz") - """ diff --git a/envs/monkey_zoo/blackbox/tests/basic_test.py b/envs/monkey_zoo/blackbox/tests/basic_test.py index f21feccb7..1715f2d12 100644 --- a/envs/monkey_zoo/blackbox/tests/basic_test.py +++ b/envs/monkey_zoo/blackbox/tests/basic_test.py @@ -29,7 +29,6 @@ class BasicTest(object): if self.all_analyzers_pass(): self.log_success(timer) return - sleep(DELAY_BETWEEN_ANALYSIS) self.log_failure(timer) assert False diff --git a/envs/monkey_zoo/blackbox/utils/monkey_island_client.py b/envs/monkey_zoo/blackbox/utils/monkey_island_client.py index 6c4cd1258..0e935a662 100644 --- a/envs/monkey_zoo/blackbox/utils/monkey_island_client.py +++ b/envs/monkey_zoo/blackbox/utils/monkey_island_client.py @@ -1,10 +1,17 @@ import json +from time import sleep import requests # SHA3-512 of '1234567890!@#$%^&*()_nothing_up_my_sleeve_1234567890!@#$%^&*()' NO_AUTH_CREDS = '55e97c9dcfd22b8079189ddaeea9bce8125887e3237b800c6176c9afa80d2062' \ '8d2c8d0b1538d2208c1444ac66535b764a3d902b35e751df3faec1e477ed3557' +SLEEP_BETWEEN_REQUESTS_SECONDS = 0.5 + + +def avoid_race_condition(func): + sleep(SLEEP_BETWEEN_REQUESTS_SECONDS) + return func class MonkeyIslandClient(object): @@ -46,9 +53,11 @@ class MonkeyIslandClient(object): def get_api_status(self): return self.request_get("api") + @avoid_race_condition def import_config(self, config_contents): _ = self.request_post("api/configuration/island", data=config_contents) + @avoid_race_condition def run_monkey_local(self): response = self.request_post_json("api/local-monkey", dict_data={"action": "run"}) if MonkeyIslandClient.monkey_ran_successfully(response): @@ -61,6 +70,7 @@ class MonkeyIslandClient(object): def monkey_ran_successfully(response): return response.ok and json.loads(response.content)['is_running'] + @avoid_race_condition def kill_all_monkeys(self): if self.request_get("api", {"action": "killall"}).ok: print("Killing all monkeys after the test.") @@ -68,6 +78,7 @@ class MonkeyIslandClient(object): print("Failed to kill all monkeys.") assert False + @avoid_race_condition def reset_env(self): if self.request_get("api", {"action": "reset"}).ok: print("Resetting environment after the test.") From 9938ba9574160198b43513926960a061baa82cfc Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Fri, 13 Sep 2019 16:12:58 +0300 Subject: [PATCH 16/25] Implemented logs --- envs/monkey_zoo/.gitignore | 1 + .../analyzers/communication_analyzer.py | 7 +- .../blackbox/island_client/__init__.py | 0 .../island_config_parser.py | 0 .../island_client/monkey_island_client.py | 86 ++++++++++++++++++ .../island_client/monkey_island_requests.py | 45 ++++++++++ .../blackbox/island_configs/HADOOP.conf | 11 +-- .../blackbox/log_handlers/__init__.py | 0 .../blackbox/log_handlers/monkey_log.py | 33 +++++++ .../blackbox/log_handlers/test_logs.py | 35 ++++++++ envs/monkey_zoo/blackbox/test_blackbox.py | 57 ++++++------ envs/monkey_zoo/blackbox/tests/basic_test.py | 18 +++- .../monkey_zoo/blackbox/utils/json_encoder.py | 9 ++ .../blackbox/utils/monkey_island_client.py | 87 ------------------- monkey/infection_monkey/model/__init__.py | 2 +- monkey/monkey_island/cc/app.py | 4 + .../cc/resources/test/log_test.py | 18 ++++ .../cc/resources/test/monkey_test.py | 5 +- 18 files changed, 285 insertions(+), 133 deletions(-) create mode 100644 envs/monkey_zoo/blackbox/island_client/__init__.py rename envs/monkey_zoo/blackbox/{utils => island_client}/island_config_parser.py (100%) create mode 100644 envs/monkey_zoo/blackbox/island_client/monkey_island_client.py create mode 100644 envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py create mode 100644 envs/monkey_zoo/blackbox/log_handlers/__init__.py create mode 100644 envs/monkey_zoo/blackbox/log_handlers/monkey_log.py create mode 100644 envs/monkey_zoo/blackbox/log_handlers/test_logs.py create mode 100644 envs/monkey_zoo/blackbox/utils/json_encoder.py delete mode 100644 envs/monkey_zoo/blackbox/utils/monkey_island_client.py create mode 100644 monkey/monkey_island/cc/resources/test/log_test.py diff --git a/envs/monkey_zoo/.gitignore b/envs/monkey_zoo/.gitignore index 5fda323da..2f9a825fb 100644 --- a/envs/monkey_zoo/.gitignore +++ b/envs/monkey_zoo/.gitignore @@ -1 +1,2 @@ gcp_keys/ +logs/ diff --git a/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py b/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py index a91850057..cc460696b 100644 --- a/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py +++ b/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py @@ -1,5 +1,3 @@ -import json - LOG_INIT_MESSAGE = "Analysis didn't run." @@ -20,9 +18,8 @@ class CommunicationAnalyzer(object): return True def did_monkey_communicate_back(self, machine_ip): - query = json.dumps({'ip_addresses': {'$elemMatch': {'$eq': machine_ip}}}) - response = self.island_client.request_get("api/test/monkey", {'find_query': query}) - return len(json.loads(response.content)['results']) > 0 + query = {'ip_addresses': {'$elemMatch': {'$eq': machine_ip}}} + return len(self.island_client.find_monkeys_in_db(query)) > 0 class AnalyzerLog(object): diff --git a/envs/monkey_zoo/blackbox/island_client/__init__.py b/envs/monkey_zoo/blackbox/island_client/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/envs/monkey_zoo/blackbox/utils/island_config_parser.py b/envs/monkey_zoo/blackbox/island_client/island_config_parser.py similarity index 100% rename from envs/monkey_zoo/blackbox/utils/island_config_parser.py rename to envs/monkey_zoo/blackbox/island_client/island_config_parser.py diff --git a/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py b/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py new file mode 100644 index 000000000..bc2e30b44 --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py @@ -0,0 +1,86 @@ +from time import sleep +import json + +from bson import json_util + +from envs.monkey_zoo.blackbox.island_client.monkey_island_requests import MonkeyIslandRequests + +SLEEP_BETWEEN_REQUESTS_SECONDS = 0.5 +MONKEY_TEST_ENDPOINT = 'api/test/monkey' +LOG_TEST_ENDPOINT = 'api/test/log' + + +def avoid_race_condition(func): + sleep(SLEEP_BETWEEN_REQUESTS_SECONDS) + return func + + +class MonkeyIslandClient(object): + def __init__(self, server_address): + self.requests = MonkeyIslandRequests(server_address) + + def get_api_status(self): + return self.requests.get("api") + + @avoid_race_condition + def import_config(self, config_contents): + _ = self.requests.post("api/configuration/island", data=config_contents) + + @avoid_race_condition + def run_monkey_local(self): + response = self.requests.post_json("api/local-monkey", dict_data={"action": "run"}) + if MonkeyIslandClient.monkey_ran_successfully(response): + print("Running the monkey.") + else: + print("Failed to run the monkey.") + assert False + + @staticmethod + def monkey_ran_successfully(response): + return response.ok and json.loads(response.content)['is_running'] + + @avoid_race_condition + def kill_all_monkeys(self): + if self.requests.get("api", {"action": "killall"}).ok: + print("Killing all monkeys after the test.") + else: + print("Failed to kill all monkeys.") + assert False + + @avoid_race_condition + def reset_env(self): + if self.requests.get("api", {"action": "reset"}).ok: + print("Resetting environment after the test.") + else: + print("Failed to reset the environment.") + assert False + + def find_monkeys_in_db(self, query): + response = self.requests.get(MONKEY_TEST_ENDPOINT, + MonkeyIslandClient.form_find_query_for_request(query)) + try: + return MonkeyIslandClient.get_test_query_results(response) + except Exception: + print("Ran into trouble parsing response for monkey query") + raise + + def find_log_in_db(self, query): + response = self.requests.get(LOG_TEST_ENDPOINT, + MonkeyIslandClient.form_find_query_for_request(query)) + try: + return MonkeyIslandClient.get_test_query_results(response) + except Exception: + print("Ran into trouble parsing response for log query") + raise + + @staticmethod + def form_find_query_for_request(query): + return {'find_query': json_util.dumps(query)} + + @staticmethod + def get_test_query_results(response): + return json.loads(response.content)['results'] + + def is_all_monkeys_dead(self): + query = {'dead': 'false'} + return len(self.find_monkeys_in_db(query)) == 0 diff --git a/envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py b/envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py new file mode 100644 index 000000000..8452f2562 --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py @@ -0,0 +1,45 @@ +import requests + +# SHA3-512 of '1234567890!@#$%^&*()_nothing_up_my_sleeve_1234567890!@#$%^&*()' +NO_AUTH_CREDS = '55e97c9dcfd22b8079189ddaeea9bce8125887e3237b800c6176c9afa80d2062' \ + '8d2c8d0b1538d2208c1444ac66535b764a3d902b35e751df3faec1e477ed3557' + + +class MonkeyIslandRequests(object): + def __init__(self, server_address): + self.addr = "https://{IP}/".format(IP=server_address) + self.token = self.try_get_jwt_from_server() + + def try_get_jwt_from_server(self): + try: + return self.get_jwt_from_server() + except requests.ConnectionError: + print("Unable to connect to island, aborting!") + assert False + + def get_jwt_from_server(self): + resp = requests.post(self.addr + "api/auth", + json={"username": NO_AUTH_CREDS, "password": NO_AUTH_CREDS}, + verify=False) + return resp.json()["access_token"] + + def get(self, url, data=None): + return requests.get(self.addr + url, + headers=self.get_jwt_header(), + params=data, + verify=False) + + def post(self, url, data): + return requests.post(self.addr + url, + data=data, + headers=self.get_jwt_header(), + verify=False) + + def post_json(self, url, dict_data): + return requests.post(self.addr + url, + json=dict_data, + headers=self.get_jwt_header(), + verify=False) + + def get_jwt_header(self): + return {"Authorization": "JWT " + self.token} diff --git a/envs/monkey_zoo/blackbox/island_configs/HADOOP.conf b/envs/monkey_zoo/blackbox/island_configs/HADOOP.conf index be97bbc26..1b55557a9 100644 --- a/envs/monkey_zoo/blackbox/island_configs/HADOOP.conf +++ b/envs/monkey_zoo/blackbox/island_configs/HADOOP.conf @@ -46,16 +46,7 @@ "exploits": { "general": { "exploiter_classes": [ - "SmbExploiter", - "WmiExploiter", - "SSHExploiter", - "ShellShockExploiter", - "SambaCryExploiter", - "ElasticGroovyExploiter", - "Struts2Exploiter", - "WebLogicExploiter", - "HadoopExploiter", - "VSFTPDExploiter" + "HadoopExploiter" ], "skip_exploit_if_file_exist": false }, diff --git a/envs/monkey_zoo/blackbox/log_handlers/__init__.py b/envs/monkey_zoo/blackbox/log_handlers/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/envs/monkey_zoo/blackbox/log_handlers/monkey_log.py b/envs/monkey_zoo/blackbox/log_handlers/monkey_log.py new file mode 100644 index 000000000..b106b6668 --- /dev/null +++ b/envs/monkey_zoo/blackbox/log_handlers/monkey_log.py @@ -0,0 +1,33 @@ +import os + +from bson import ObjectId + + +class MonkeyLog(object): + def __init__(self, monkey, log_dir_path): + self.monkey = monkey + self.log_dir_path = log_dir_path + + def download_log(self, island_client): + log = island_client.find_log_in_db({'monkey_id': ObjectId(self.monkey['id'])}) + if not log: + print("Log for monkey {} not found".format(self.monkey['ip_addresses'][0])) + else: + self.write_log_to_file(log) + + def write_log_to_file(self, log): + with open(self.get_log_path_for_monkey(self.monkey), 'w') as log_file: + log_file.write(MonkeyLog.parse_log(log)) + + @staticmethod + def parse_log(log): + log = log.strip('"') + log = log.replace("\\n", "\n ") + return log + + @staticmethod + def get_filename_for_monkey_log(monkey): + return "{}.txt".format(monkey['ip_addresses'][0]) + + def get_log_path_for_monkey(self, monkey): + return os.path.join(self.log_dir_path, MonkeyLog.get_filename_for_monkey_log(monkey)) diff --git a/envs/monkey_zoo/blackbox/log_handlers/test_logs.py b/envs/monkey_zoo/blackbox/log_handlers/test_logs.py new file mode 100644 index 000000000..47d0bad62 --- /dev/null +++ b/envs/monkey_zoo/blackbox/log_handlers/test_logs.py @@ -0,0 +1,35 @@ +import os +import shutil + +from envs.monkey_zoo.blackbox.log_handlers.monkey_log import MonkeyLog + +LOG_DIR_NAME = 'logs' + + +class TestLogsHandler(object): + def __init__(self, test_name, island_client): + self.test_name = test_name + self.island_client = island_client + self.log_dir_path = os.path.join(TestLogsHandler.get_log_dir_path(), self.test_name) + + def download_logs(self): + self.try_create_log_dir_for_test() + print("Downloading logs") + all_monkeys = self.island_client.find_monkeys_in_db(None) + for monkey in all_monkeys: + MonkeyLog(monkey, self.log_dir_path).download_log(self.island_client) + + def try_create_log_dir_for_test(self): + try: + os.mkdir(self.log_dir_path) + except Exception as e: + print("Can't create a dir for test logs: {}".format(e)) + + @staticmethod + def get_log_dir_path(): + return os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), LOG_DIR_NAME) + + @staticmethod + def delete_log_folder_contents(): + shutil.rmtree(TestLogsHandler.get_log_dir_path(), ignore_errors=True) + os.mkdir(TestLogsHandler.get_log_dir_path()) diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index 1c747cb77..1799166a2 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -1,15 +1,15 @@ +import pytest from time import sleep -import pytest - -from envs.monkey_zoo.blackbox.utils.monkey_island_client import MonkeyIslandClient +from envs.monkey_zoo.blackbox.island_client.monkey_island_client import MonkeyIslandClient from envs.monkey_zoo.blackbox.analyzers.communication_analyzer import CommunicationAnalyzer -from envs.monkey_zoo.blackbox.utils.island_config_parser import IslandConfigParser +from envs.monkey_zoo.blackbox.island_client.island_config_parser import IslandConfigParser from envs.monkey_zoo.blackbox.utils import gcp_machine_handlers from envs.monkey_zoo.blackbox.tests.basic_test import BasicTest +from envs.monkey_zoo.blackbox.log_handlers.test_logs import TestLogsHandler -DEFAULT_TIMEOUT_SECONDS = 3 * 60 -DELAY_BETWEEN_TESTS = 30 +DEFAULT_TIMEOUT_SECONDS = 4*60 +MACHINE_BOOTUP_WAIT_SECONDS = 30 GCP_TEST_MACHINE_LIST = ['sshkeys-11', 'sshkeys-12', 'elastic-4', 'elastic-5', 'haddop-2-v3', 'hadoop-3', 'mssql-16', 'mimikatz-14', 'mimikatz-15', 'final-test-struts2-23', 'final-test-struts2-24', 'tunneling-9', 'tunneling-10', 'tunneling-11', 'weblogic-18', 'weblogic-19', 'shellshock-8'] @@ -18,15 +18,25 @@ GCP_TEST_MACHINE_LIST = ['sshkeys-11', 'sshkeys-12', 'elastic-4', 'elastic-5', ' @pytest.fixture(autouse=True, scope='session') def GCPHandler(request): GCPHandler = gcp_machine_handlers.GCPHandler() - #GCPHandler.start_machines(" ".join(GCP_TEST_MACHINE_LIST)) + GCPHandler.start_machines(" ".join(GCP_TEST_MACHINE_LIST)) + wait_machine_bootup() def fin(): - pass - # GCPHandler.stop_machines(" ".join(GCP_TEST_MACHINE_LIST)) + GCPHandler.stop_machines(" ".join(GCP_TEST_MACHINE_LIST)) request.addfinalizer(fin) +@pytest.fixture(autouse=True, scope='session') +def delete_logs(): + print("Deleting monkey logs before new tests.") + TestLogsHandler.delete_log_folder_contents() + + +def wait_machine_bootup(): + sleep(MACHINE_BOOTUP_WAIT_SECONDS) + + @pytest.fixture(scope='class') def island_client(island): island_client_object = MonkeyIslandClient(island) @@ -37,8 +47,8 @@ def island_client(island): # noinspection PyUnresolvedReferences class TestMonkeyBlackbox(object): - def run_basic_test(self, island_client, conf_filename, test_name, timeout_in_seconds=DEFAULT_TIMEOUT_SECONDS): - TestMonkeyBlackbox.wait_between_tests() + @staticmethod + def run_basic_test(island_client, conf_filename, test_name, timeout_in_seconds=DEFAULT_TIMEOUT_SECONDS): config_parser = IslandConfigParser(conf_filename) analyzer = CommunicationAnalyzer(island_client, config_parser.get_ips_of_targets()) BasicTest(test_name, @@ -47,44 +57,39 @@ class TestMonkeyBlackbox(object): [analyzer], timeout_in_seconds).run() - @staticmethod - def wait_between_tests(): - print("Waiting for ({:.0f} seconds) for old monkey's to die or GCP machines to boot up.".format(DELAY_BETWEEN_TESTS)) - sleep(DELAY_BETWEEN_TESTS) - def test_server_online(self, island_client): assert island_client.get_api_status() is not None def test_ssh_exploiter(self, island_client): - self.run_basic_test(island_client, "SSH.conf", "SSH exploiter and keys") + TestMonkeyBlackbox.run_basic_test(island_client, "SSH.conf", "SSH_exploiter_and_keys") def test_hadoop_exploiter(self, island_client): - self.run_basic_test(island_client, "HADOOP.conf", "Hadoop exploiter") + TestMonkeyBlackbox.run_basic_test(island_client, "HADOOP.conf", "Hadoop_exploiter", 6*60) """ def test_mssql_exploiter(self, island_client): - self.run_basic_test(island_client, "MSSQL.conf", "MSSQL exploiter") + TestMonkeyBlackbox.run_basic_test(island_client, "MSSQL.conf", "MSSQL_exploiter") """ def test_smb_and_mimikatz_exploiters(self, island_client): - self.run_basic_test(island_client, "SMB_MIMIKATZ.conf", "SMB exploiter, mimikatz") + TestMonkeyBlackbox.run_basic_test(island_client, "SMB_MIMIKATZ.conf", "SMB_exploiter_mimikatz") """ def test_elastic_exploiter(self, island_client): - self.run_basic_test(island_client, "ELASTIC.conf", "Elastic exploiter") + TestMonkeyBlackbox.run_basic_test(island_client, "ELASTIC.conf", "Elastic_exploiter") """ def test_struts_exploiter(self, island_client): - self.run_basic_test(island_client, "STRUTS2.conf", "Strtuts2 exploiter") + TestMonkeyBlackbox.run_basic_test(island_client, "STRUTS2.conf", "Strtuts2_exploiter") def test_weblogic_exploiter(self, island_client): - self.run_basic_test(island_client, "WEBLOGIC.conf", "Weblogic exploiter") + TestMonkeyBlackbox.run_basic_test(island_client, "WEBLOGIC.conf", "Weblogic_exploiter") def test_shellshock_exploiter(self, island_client): - self.run_basic_test(island_client, "SHELLSHOCK.conf", "Shellschock exploiter") + TestMonkeyBlackbox.run_basic_test(island_client, "SHELLSHOCK.conf", "Shellschock_exploiter") def test_tunneling(self, island_client): - self.run_basic_test(island_client, "TUNNELING.conf", "Tunneling exploiter") + TestMonkeyBlackbox.run_basic_test(island_client, "TUNNELING.conf", "Tunneling_exploiter") def test_wmi_exploiter(self, island_client): - self.run_basic_test(island_client, "WMI_MIMIKATZ.conf", "WMI exploiter, mimikatz") + TestMonkeyBlackbox.run_basic_test(island_client, "WMI_MIMIKATZ.conf", "WMI_exploiter,_mimikatz") diff --git a/envs/monkey_zoo/blackbox/tests/basic_test.py b/envs/monkey_zoo/blackbox/tests/basic_test.py index 1715f2d12..ccc5c6770 100644 --- a/envs/monkey_zoo/blackbox/tests/basic_test.py +++ b/envs/monkey_zoo/blackbox/tests/basic_test.py @@ -1,8 +1,10 @@ from time import sleep from envs.monkey_zoo.blackbox.utils.test_timer import TestTimer +from envs.monkey_zoo.blackbox.log_handlers.test_logs import TestLogsHandler -DELAY_BETWEEN_ANALYSIS = 1 +MAX_TIME_FOR_MONKEYS_TO_DIE = 5*60 +WAIT_TIME_BETWEEN_REQUESTS = 10 class BasicTest(object): @@ -19,8 +21,13 @@ class BasicTest(object): try: self.island_client.run_monkey_local() self.test_until_timeout() + except AssertionError: + print("Test {} failed. Downloading logs of all monkeys.".format(self.name)) + TestLogsHandler(self.name, self.island_client).download_logs() + raise finally: self.island_client.kill_all_monkeys() + self.wait_until_monkeys_die() self.island_client.reset_env() def test_until_timeout(self): @@ -52,3 +59,12 @@ class BasicTest(object): for analyzer in self.analyzers: log += "\n"+analyzer.log.get_contents() return log + + def wait_until_monkeys_die(self): + time_passed = 0 + while not self.island_client.is_all_monkeys_dead() and time_passed < MAX_TIME_FOR_MONKEYS_TO_DIE: + sleep(WAIT_TIME_BETWEEN_REQUESTS) + time_passed += WAIT_TIME_BETWEEN_REQUESTS + if time_passed > MAX_TIME_FOR_MONKEYS_TO_DIE: + print("Some monkeys didn't die after the test, passing") + assert False diff --git a/envs/monkey_zoo/blackbox/utils/json_encoder.py b/envs/monkey_zoo/blackbox/utils/json_encoder.py new file mode 100644 index 000000000..77be9211a --- /dev/null +++ b/envs/monkey_zoo/blackbox/utils/json_encoder.py @@ -0,0 +1,9 @@ +import json +from bson import ObjectId + + +class MongoQueryJSONEncoder(json.JSONEncoder): + def default(self, o): + if isinstance(o, ObjectId): + return str(o) + return json.JSONEncoder.default(self, o) diff --git a/envs/monkey_zoo/blackbox/utils/monkey_island_client.py b/envs/monkey_zoo/blackbox/utils/monkey_island_client.py deleted file mode 100644 index 0e935a662..000000000 --- a/envs/monkey_zoo/blackbox/utils/monkey_island_client.py +++ /dev/null @@ -1,87 +0,0 @@ -import json -from time import sleep - -import requests - -# SHA3-512 of '1234567890!@#$%^&*()_nothing_up_my_sleeve_1234567890!@#$%^&*()' -NO_AUTH_CREDS = '55e97c9dcfd22b8079189ddaeea9bce8125887e3237b800c6176c9afa80d2062' \ - '8d2c8d0b1538d2208c1444ac66535b764a3d902b35e751df3faec1e477ed3557' -SLEEP_BETWEEN_REQUESTS_SECONDS = 0.5 - - -def avoid_race_condition(func): - sleep(SLEEP_BETWEEN_REQUESTS_SECONDS) - return func - - -class MonkeyIslandClient(object): - def __init__(self, server_address): - self.addr = "https://{IP}/".format(IP=server_address) - self.token = self.try_get_jwt_from_server() - - def try_get_jwt_from_server(self): - try: - return self.get_jwt_from_server() - except requests.ConnectionError: - print("Unable to connect to island, aborting!") - assert False - - def get_jwt_from_server(self): - resp = requests.post(self.addr + "api/auth", - json={"username": NO_AUTH_CREDS, "password": NO_AUTH_CREDS}, - verify=False) - return resp.json()["access_token"] - - def request_get(self, url, data=None): - return requests.get(self.addr + url, - headers={"Authorization": "JWT " + self.token}, - params=data, - verify=False) - - def request_post(self, url, data): - return requests.post(self.addr + url, - data=data, - headers={"Authorization": "JWT " + self.token}, - verify=False) - - def request_post_json(self, url, dict_data): - return requests.post(self.addr + url, - json=dict_data, - headers={"Authorization": "JWT " + self.token}, - verify=False) - - def get_api_status(self): - return self.request_get("api") - - @avoid_race_condition - def import_config(self, config_contents): - _ = self.request_post("api/configuration/island", data=config_contents) - - @avoid_race_condition - def run_monkey_local(self): - response = self.request_post_json("api/local-monkey", dict_data={"action": "run"}) - if MonkeyIslandClient.monkey_ran_successfully(response): - print("Running the monkey.") - else: - print("Failed to run the monkey.") - assert False - - @staticmethod - def monkey_ran_successfully(response): - return response.ok and json.loads(response.content)['is_running'] - - @avoid_race_condition - def kill_all_monkeys(self): - if self.request_get("api", {"action": "killall"}).ok: - print("Killing all monkeys after the test.") - else: - print("Failed to kill all monkeys.") - assert False - - @avoid_race_condition - def reset_env(self): - if self.request_get("api", {"action": "reset"}).ok: - print("Resetting environment after the test.") - else: - print("Failed to reset the environment.") - assert False diff --git a/monkey/infection_monkey/model/__init__.py b/monkey/infection_monkey/model/__init__.py index dd3e9ca63..3e333a26d 100644 --- a/monkey/infection_monkey/model/__init__.py +++ b/monkey/infection_monkey/model/__init__.py @@ -38,4 +38,4 @@ HADOOP_LINUX_COMMAND = "! [ -f %(monkey_path)s ] " \ "; chmod +x %(monkey_path)s " \ "&& %(monkey_path)s %(monkey_type)s %(parameters)s" -DOWNLOAD_TIMEOUT = 300 +DOWNLOAD_TIMEOUT = 180 diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py index 7d27995ab..f4d3c6a40 100644 --- a/monkey/monkey_island/cc/app.py +++ b/monkey/monkey_island/cc/app.py @@ -35,7 +35,9 @@ from monkey_island.cc.services.remote_run_aws import RemoteRunAwsService from monkey_island.cc.resources.pba_file_upload import FileUpload from monkey_island.cc.resources.attack.attack_config import AttackConfiguration from monkey_island.cc.resources.attack.attack_report import AttackReport + from monkey_island.cc.resources.test.monkey_test import MonkeyTest +from monkey_island.cc.resources.test.log_test import LogTest __author__ = 'Barak' @@ -135,7 +137,9 @@ def init_api_resources(api): api.add_resource(AttackConfiguration, '/api/attack') api.add_resource(AttackReport, '/api/attack/report') api.add_resource(VersionUpdate, '/api/version-update', '/api/version-update/') + api.add_resource(MonkeyTest, '/api/test/monkey') + api.add_resource(LogTest, '/api/test/log') def init_app(mongo_url): diff --git a/monkey/monkey_island/cc/resources/test/log_test.py b/monkey/monkey_island/cc/resources/test/log_test.py new file mode 100644 index 000000000..e592e7214 --- /dev/null +++ b/monkey/monkey_island/cc/resources/test/log_test.py @@ -0,0 +1,18 @@ +from bson import json_util +import flask_restful +from flask import request + + +from monkey_island.cc.auth import jwt_required +from monkey_island.cc.database import mongo, database + + +class LogTest(flask_restful.Resource): + @jwt_required() + def get(self): + find_query = json_util.loads(request.args.get('find_query')) + log = mongo.db.log.find_one(find_query) + if not log: + return {'results': None} + log_file = database.gridfs.get(log['file_id']) + return {'results': log_file.read()} diff --git a/monkey/monkey_island/cc/resources/test/monkey_test.py b/monkey/monkey_island/cc/resources/test/monkey_test.py index 365f30dc9..100624780 100644 --- a/monkey/monkey_island/cc/resources/test/monkey_test.py +++ b/monkey/monkey_island/cc/resources/test/monkey_test.py @@ -1,5 +1,4 @@ -import json - +from bson import json_util import flask_restful from flask import request @@ -10,5 +9,5 @@ from monkey_island.cc.database import mongo class MonkeyTest(flask_restful.Resource): @jwt_required() def get(self, **kw): - find_query = json.loads(request.args.get('find_query')) + find_query = json_util.loads(request.args.get('find_query')) return {'results': list(mongo.db.monkey.find(find_query))} From e0a38f3b19ee827066c1f50f6835fa47b91c2aaf Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Fri, 13 Sep 2019 16:40:43 +0300 Subject: [PATCH 17/25] Refactored gitignore to include gcp_keys directory but not it's contents --- envs/monkey_zoo/.gitignore | 1 - envs/monkey_zoo/gcp_keys/.gitignore | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 envs/monkey_zoo/gcp_keys/.gitignore diff --git a/envs/monkey_zoo/.gitignore b/envs/monkey_zoo/.gitignore index 2f9a825fb..333c1e910 100644 --- a/envs/monkey_zoo/.gitignore +++ b/envs/monkey_zoo/.gitignore @@ -1,2 +1 @@ -gcp_keys/ logs/ diff --git a/envs/monkey_zoo/gcp_keys/.gitignore b/envs/monkey_zoo/gcp_keys/.gitignore new file mode 100644 index 000000000..5e7d2734c --- /dev/null +++ b/envs/monkey_zoo/gcp_keys/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore From 91fe7c22a893de4ea86fd99491591444b53bf4ea Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Fri, 13 Sep 2019 16:50:12 +0300 Subject: [PATCH 18/25] Removed comments that were used in testing --- envs/monkey_zoo/blackbox/test_blackbox.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index 1799166a2..dcf345345 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -66,18 +66,14 @@ class TestMonkeyBlackbox(object): def test_hadoop_exploiter(self, island_client): TestMonkeyBlackbox.run_basic_test(island_client, "HADOOP.conf", "Hadoop_exploiter", 6*60) - """ def test_mssql_exploiter(self, island_client): - TestMonkeyBlackbox.run_basic_test(island_client, "MSSQL.conf", "MSSQL_exploiter") - """ + TestMonkeyBlackbox.run_basic_test(island_client, "MSSQL.conf", "MSSQL_exploiter") def test_smb_and_mimikatz_exploiters(self, island_client): TestMonkeyBlackbox.run_basic_test(island_client, "SMB_MIMIKATZ.conf", "SMB_exploiter_mimikatz") - """ def test_elastic_exploiter(self, island_client): TestMonkeyBlackbox.run_basic_test(island_client, "ELASTIC.conf", "Elastic_exploiter") - """ def test_struts_exploiter(self, island_client): TestMonkeyBlackbox.run_basic_test(island_client, "STRUTS2.conf", "Strtuts2_exploiter") From 018d3ddc0863565925e0c6f8d82122213a9244f7 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Tue, 17 Sep 2019 09:17:29 +0300 Subject: [PATCH 19/25] Fixed bugs regarding waiting for monkeys to die, readability improvements --- .../blackbox/analyzers/analyzer_log.py | 17 ++++++++++ .../analyzers/communication_analyzer.py | 26 ++++----------- .../island_client/monkey_island_client.py | 2 +- .../blackbox/log_handlers/log_parser.py | 32 +++++++++++++++++++ .../blackbox/log_handlers/logs_downloader.py | 22 +++++++++++++ .../blackbox/log_handlers/monkey_log.py | 2 ++ .../{test_logs.py => test_logs_handler.py} | 25 ++++++++++++--- envs/monkey_zoo/blackbox/test_blackbox.py | 4 +-- envs/monkey_zoo/blackbox/tests/basic_test.py | 31 +++++++++++++----- 9 files changed, 125 insertions(+), 36 deletions(-) create mode 100644 envs/monkey_zoo/blackbox/analyzers/analyzer_log.py create mode 100644 envs/monkey_zoo/blackbox/log_handlers/log_parser.py create mode 100644 envs/monkey_zoo/blackbox/log_handlers/logs_downloader.py rename envs/monkey_zoo/blackbox/log_handlers/{test_logs.py => test_logs_handler.py} (52%) diff --git a/envs/monkey_zoo/blackbox/analyzers/analyzer_log.py b/envs/monkey_zoo/blackbox/analyzers/analyzer_log.py new file mode 100644 index 000000000..f97418813 --- /dev/null +++ b/envs/monkey_zoo/blackbox/analyzers/analyzer_log.py @@ -0,0 +1,17 @@ +LOG_INIT_MESSAGE = "Analysis didn't run." + + +class AnalyzerLog(object): + + def __init__(self, analyzer_name): + self.contents = LOG_INIT_MESSAGE + self.name = analyzer_name + + def clear(self): + self.contents = "" + + def add_entry(self, message): + self.contents = "{}\n{}".format(self.contents, message) + + def get_contents(self): + return "{}: {}\n".format(self.name, self.contents) diff --git a/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py b/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py index cc460696b..491b534b8 100644 --- a/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py +++ b/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py @@ -1,4 +1,4 @@ -LOG_INIT_MESSAGE = "Analysis didn't run." +from envs.monkey_zoo.blackbox.analyzers.analyzer_log import AnalyzerLog class CommunicationAnalyzer(object): @@ -10,29 +10,15 @@ class CommunicationAnalyzer(object): def analyze_test_results(self): self.log.clear() + all_monkeys_communicated = True for machine_ip in self.machine_ips: if not self.did_monkey_communicate_back(machine_ip): self.log.add_entry("Monkey from {} didn't communicate back".format(machine_ip)) - return False - self.log.add_entry("Monkey from {} communicated back".format(machine_ip)) - return True + all_monkeys_communicated = False + else: + self.log.add_entry("Monkey from {} communicated back".format(machine_ip)) + return all_monkeys_communicated def did_monkey_communicate_back(self, machine_ip): query = {'ip_addresses': {'$elemMatch': {'$eq': machine_ip}}} return len(self.island_client.find_monkeys_in_db(query)) > 0 - - -class AnalyzerLog(object): - - def __init__(self, analyzer_name): - self.contents = LOG_INIT_MESSAGE - self.name = analyzer_name - - def clear(self): - self.contents = "" - - def add_entry(self, message): - self.contents = "{}\n{}".format(self.contents, message) - - def get_contents(self): - return "{}: {}\n".format(self.name, self.contents) diff --git a/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py b/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py index bc2e30b44..a06617b08 100644 --- a/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py +++ b/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py @@ -82,5 +82,5 @@ class MonkeyIslandClient(object): return json.loads(response.content)['results'] def is_all_monkeys_dead(self): - query = {'dead': 'false'} + query = {'dead': False} return len(self.find_monkeys_in_db(query)) == 0 diff --git a/envs/monkey_zoo/blackbox/log_handlers/log_parser.py b/envs/monkey_zoo/blackbox/log_handlers/log_parser.py new file mode 100644 index 000000000..9f3c34f57 --- /dev/null +++ b/envs/monkey_zoo/blackbox/log_handlers/log_parser.py @@ -0,0 +1,32 @@ +import re + + +class LogParser(object): + + def __init__(self, log_path): + self.log_path = log_path + self.log_contents = self.read_log() + + def read_log(self): + with open(self.log_path, 'r') as log: + return log.read() + + def print_errors(self): + print("Errors:") + for error_line in LogParser.get_errors(self.log_contents): + print(error_line) + + @staticmethod + def get_errors(log_contents): + searcher = re.compile(r"^.*:ERROR].*$", re.MULTILINE) + return searcher.findall(log_contents) + + def print_warnings(self): + print("Warnings:") + for warning_line in LogParser.get_warnings(self.log_contents): + print(warning_line) + + @staticmethod + def get_warnings(log_contents): + searcher = re.compile(r"^.*:WARNING].*$", re.MULTILINE) + return searcher.findall(log_contents) diff --git a/envs/monkey_zoo/blackbox/log_handlers/logs_downloader.py b/envs/monkey_zoo/blackbox/log_handlers/logs_downloader.py new file mode 100644 index 000000000..446960147 --- /dev/null +++ b/envs/monkey_zoo/blackbox/log_handlers/logs_downloader.py @@ -0,0 +1,22 @@ +from envs.monkey_zoo.blackbox.log_handlers.monkey_log import MonkeyLog + + +class LogsDownloader(object): + + def __init__(self, island_client, log_dir_path): + self.island_client = island_client + self.log_dir_path = log_dir_path + self.monkey_log_paths = [] + + def download_monkey_logs(self): + print("Downloading each monkey log.") + all_monkeys = self.island_client.find_monkeys_in_db(None) + for monkey in all_monkeys: + downloaded_log_path = self._download_monkey_log(monkey) + if downloaded_log_path: + self.monkey_log_paths.append(downloaded_log_path) + + def _download_monkey_log(self, monkey): + log_handler = MonkeyLog(monkey, self.log_dir_path) + download_successful = log_handler.download_log(self.island_client) + return log_handler.get_log_path_for_monkey(monkey) if download_successful else None diff --git a/envs/monkey_zoo/blackbox/log_handlers/monkey_log.py b/envs/monkey_zoo/blackbox/log_handlers/monkey_log.py index b106b6668..bcc304535 100644 --- a/envs/monkey_zoo/blackbox/log_handlers/monkey_log.py +++ b/envs/monkey_zoo/blackbox/log_handlers/monkey_log.py @@ -12,8 +12,10 @@ class MonkeyLog(object): log = island_client.find_log_in_db({'monkey_id': ObjectId(self.monkey['id'])}) if not log: print("Log for monkey {} not found".format(self.monkey['ip_addresses'][0])) + return False else: self.write_log_to_file(log) + return True def write_log_to_file(self, log): with open(self.get_log_path_for_monkey(self.monkey), 'w') as log_file: diff --git a/envs/monkey_zoo/blackbox/log_handlers/test_logs.py b/envs/monkey_zoo/blackbox/log_handlers/test_logs_handler.py similarity index 52% rename from envs/monkey_zoo/blackbox/log_handlers/test_logs.py rename to envs/monkey_zoo/blackbox/log_handlers/test_logs_handler.py index 47d0bad62..e2c87a320 100644 --- a/envs/monkey_zoo/blackbox/log_handlers/test_logs.py +++ b/envs/monkey_zoo/blackbox/log_handlers/test_logs_handler.py @@ -1,7 +1,8 @@ import os import shutil -from envs.monkey_zoo.blackbox.log_handlers.monkey_log import MonkeyLog +from envs.monkey_zoo.blackbox.log_handlers.log_parser import LogParser +from envs.monkey_zoo.blackbox.log_handlers.logs_downloader import LogsDownloader LOG_DIR_NAME = 'logs' @@ -12,12 +13,18 @@ class TestLogsHandler(object): self.island_client = island_client self.log_dir_path = os.path.join(TestLogsHandler.get_log_dir_path(), self.test_name) + def parse_test_logs(self): + log_paths = self.download_logs() + if not log_paths: + print("No logs were downloaded, maybe no monkeys were ran?") + return + TestLogsHandler.parse_logs(log_paths) + def download_logs(self): self.try_create_log_dir_for_test() - print("Downloading logs") - all_monkeys = self.island_client.find_monkeys_in_db(None) - for monkey in all_monkeys: - MonkeyLog(monkey, self.log_dir_path).download_log(self.island_client) + downloader = LogsDownloader(self.island_client, self.log_dir_path) + downloader.download_monkey_logs() + return downloader.monkey_log_paths def try_create_log_dir_for_test(self): try: @@ -33,3 +40,11 @@ class TestLogsHandler(object): def delete_log_folder_contents(): shutil.rmtree(TestLogsHandler.get_log_dir_path(), ignore_errors=True) os.mkdir(TestLogsHandler.get_log_dir_path()) + + @staticmethod + def parse_logs(log_paths): + for log_path in log_paths: + print("Info from log at {}".format(log_path)) + log_parser = LogParser(log_path) + log_parser.print_errors() + log_parser.print_warnings() diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index dcf345345..2d80472ba 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -6,7 +6,7 @@ from envs.monkey_zoo.blackbox.analyzers.communication_analyzer import Communicat from envs.monkey_zoo.blackbox.island_client.island_config_parser import IslandConfigParser from envs.monkey_zoo.blackbox.utils import gcp_machine_handlers from envs.monkey_zoo.blackbox.tests.basic_test import BasicTest -from envs.monkey_zoo.blackbox.log_handlers.test_logs import TestLogsHandler +from envs.monkey_zoo.blackbox.log_handlers.test_logs_handler import TestLogsHandler DEFAULT_TIMEOUT_SECONDS = 4*60 MACHINE_BOOTUP_WAIT_SECONDS = 30 @@ -53,7 +53,7 @@ class TestMonkeyBlackbox(object): analyzer = CommunicationAnalyzer(island_client, config_parser.get_ips_of_targets()) BasicTest(test_name, island_client, - config_parser.config_raw, + config_parser, [analyzer], timeout_in_seconds).run() diff --git a/envs/monkey_zoo/blackbox/tests/basic_test.py b/envs/monkey_zoo/blackbox/tests/basic_test.py index ccc5c6770..2b544a9f1 100644 --- a/envs/monkey_zoo/blackbox/tests/basic_test.py +++ b/envs/monkey_zoo/blackbox/tests/basic_test.py @@ -1,35 +1,42 @@ from time import sleep from envs.monkey_zoo.blackbox.utils.test_timer import TestTimer -from envs.monkey_zoo.blackbox.log_handlers.test_logs import TestLogsHandler +from envs.monkey_zoo.blackbox.log_handlers.test_logs_handler import TestLogsHandler MAX_TIME_FOR_MONKEYS_TO_DIE = 5*60 WAIT_TIME_BETWEEN_REQUESTS = 10 +TIME_FOR_MONKEY_PROCESS_TO_FINISH = 20 class BasicTest(object): - def __init__(self, name, island_client, island_config, analyzers, timeout): + def __init__(self, name, island_client, config_parser, analyzers, timeout): self.name = name self.island_client = island_client - self.island_config = island_config + self.config_parser = config_parser self.analyzers = analyzers self.timeout = timeout def run(self): - self.island_client.import_config(self.island_config) + self.island_client.import_config(self.config_parser.config_raw) + self.print_test_starting_info() try: self.island_client.run_monkey_local() self.test_until_timeout() - except AssertionError: - print("Test {} failed. Downloading logs of all monkeys.".format(self.name)) - TestLogsHandler(self.name, self.island_client).download_logs() - raise finally: self.island_client.kill_all_monkeys() self.wait_until_monkeys_die() + self.wait_for_monkey_process_to_finish() + self.parse_logs() self.island_client.reset_env() + def print_test_starting_info(self): + print("Started {} test".format(self.name)) + print("Machines participating in test:") + for target_ip in self.config_parser.get_ips_of_targets(): + print(" "+target_ip) + print("") + def test_until_timeout(self): timer = TestTimer(self.timeout) while not timer.timed_out(): @@ -68,3 +75,11 @@ class BasicTest(object): if time_passed > MAX_TIME_FOR_MONKEYS_TO_DIE: print("Some monkeys didn't die after the test, passing") assert False + + def parse_logs(self): + print("\nParsing test logs:") + TestLogsHandler(self.name, self.island_client).parse_test_logs() + + @staticmethod + def wait_for_monkey_process_to_finish(): + sleep(TIME_FOR_MONKEY_PROCESS_TO_FINISH) From 896e6e486f16395ab0d51bd440c31ebf5daab20b Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Thu, 19 Sep 2019 14:38:17 +0300 Subject: [PATCH 20/25] Added env. reset before tests --- envs/monkey_zoo/blackbox/test_blackbox.py | 1 + 1 file changed, 1 insertion(+) diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index 2d80472ba..4a2c7f99d 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -40,6 +40,7 @@ def wait_machine_bootup(): @pytest.fixture(scope='class') def island_client(island): island_client_object = MonkeyIslandClient(island) + island_client_object.reset_env() yield island_client_object From 72e30bb6318f0fc1016b76a012356577630549f0 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Tue, 24 Sep 2019 15:38:16 +0300 Subject: [PATCH 21/25] Added 2 PTH tests, changed consts to improve stability --- .../blackbox/island_configs/SMB_PTH.conf | 180 +++++++++++++++++ .../blackbox/island_configs/WMI_PTH.conf | 188 ++++++++++++++++++ envs/monkey_zoo/blackbox/test_blackbox.py | 12 +- envs/monkey_zoo/blackbox/tests/basic_test.py | 2 +- 4 files changed, 378 insertions(+), 4 deletions(-) create mode 100644 envs/monkey_zoo/blackbox/island_configs/SMB_PTH.conf create mode 100644 envs/monkey_zoo/blackbox/island_configs/WMI_PTH.conf diff --git a/envs/monkey_zoo/blackbox/island_configs/SMB_PTH.conf b/envs/monkey_zoo/blackbox/island_configs/SMB_PTH.conf new file mode 100644 index 000000000..d17e283c8 --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_configs/SMB_PTH.conf @@ -0,0 +1,180 @@ +{ + "basic": { + "credentials": { + "exploit_password_list": [ + "Password1!" + ], + "exploit_user_list": [ + "Administrator", + "m0nk3y", + "user" + ] + }, + "general": { + "should_exploit": true + } + }, + "basic_network": { + "general": { + "blocked_ips": [], + "depth": 2, + "local_network_scan": false, + "subnet_scan_list": [ + "10.2.2.15" + ] + }, + "network_analysis": { + "inaccessible_subnets": [] + } + }, + "cnc": { + "servers": { + "command_servers": [ + "10.2.2.251:5000" + ], + "current_server": "10.2.2.251:5000", + "internet_services": [ + "monkey.guardicore.com", + "www.google.com" + ] + } + }, + "exploits": { + "general": { + "exploiter_classes": [ + "SmbExploiter" + ], + "skip_exploit_if_file_exist": false + }, + "ms08_067": { + "ms08_067_exploit_attempts": 5, + "remote_user_pass": "Password1!", + "user_to_add": "Monkey_IUSER_SUPPORT" + }, + "rdp_grinder": { + "rdp_use_vbs_download": true + }, + "sambacry": { + "sambacry_folder_paths_to_guess": [ + "/", + "/mnt", + "/tmp", + "/storage", + "/export", + "/share", + "/shares", + "/home" + ], + "sambacry_shares_not_to_check": [ + "IPC$", + "print$" + ], + "sambacry_trigger_timeout": 5 + }, + "smb_service": { + "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey" + } + }, + "internal": { + "classes": { + "finger_classes": [ + "SMBFinger", + "SSHFinger", + "PingScanner", + "HTTPFinger", + "MySQLFinger", + "MSSQLFinger", + "ElasticFinger" + ] + }, + "dropper": { + "dropper_date_reference_path_linux": "/bin/sh", + "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", + "dropper_set_date": true, + "dropper_target_path_linux": "/tmp/monkey", + "dropper_target_path_win_32": "C:\\Windows\\temp\\monkey32.exe", + "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", + "dropper_try_move_first": true + }, + "exploits": { + "exploit_lm_hash_list": [], + "exploit_ntlm_hash_list": [ "f7e457346f7743daece17258667c936d" ], + "exploit_ssh_keys": [] + }, + "general": { + "keep_tunnel_open_time": 1, + "monkey_dir_name": "monkey_dir", + "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" + }, + "kill_file": { + "kill_file_path_linux": "/var/run/monkey.not", + "kill_file_path_windows": "%windir%\\monkey.not" + }, + "logging": { + "dropper_log_path_linux": "/tmp/user-1562", + "dropper_log_path_windows": "%temp%\\~df1562.tmp", + "monkey_log_path_linux": "/tmp/user-1563", + "monkey_log_path_windows": "%temp%\\~df1563.tmp", + "send_log_to_server": true + } + }, + "monkey": { + "behaviour": { + "PBA_linux_filename": "", + "PBA_windows_filename": "", + "custom_PBA_linux_cmd": "", + "custom_PBA_windows_cmd": "", + "self_delete_in_cleanup": true, + "serialize_config": false, + "use_file_logging": true + }, + "general": { + "alive": true, + "post_breach_actions": [] + }, + "life_cycle": { + "max_iterations": 1, + "retry_failed_explotation": true, + "timeout_between_iterations": 100, + "victims_max_exploit": 7, + "victims_max_find": 30 + }, + "system_info": { + "collect_system_info": true, + "extract_azure_creds": true, + "should_use_mimikatz": true + } + }, + "network": { + "ping_scanner": { + "ping_scan_timeout": 1000 + }, + "tcp_scanner": { + "HTTP_PORTS": [ + 80, + 8080, + 443, + 8008, + 7001 + ], + "tcp_scan_get_banner": true, + "tcp_scan_interval": 0, + "tcp_scan_timeout": 3000, + "tcp_target_ports": [ + 22, + 2222, + 445, + 135, + 3389, + 80, + 8080, + 443, + 8008, + 3306, + 9200, + 7001 + ] + } + } +} diff --git a/envs/monkey_zoo/blackbox/island_configs/WMI_PTH.conf b/envs/monkey_zoo/blackbox/island_configs/WMI_PTH.conf new file mode 100644 index 000000000..1ac0a6c3d --- /dev/null +++ b/envs/monkey_zoo/blackbox/island_configs/WMI_PTH.conf @@ -0,0 +1,188 @@ +{ + "basic": { + "credentials": { + "exploit_password_list": [ + "Password1!" + ], + "exploit_user_list": [ + "Administrator", + "m0nk3y", + "user" + ] + }, + "general": { + "should_exploit": true + } + }, + "basic_network": { + "general": { + "blocked_ips": [], + "depth": 2, + "local_network_scan": false, + "subnet_scan_list": [ + "10.2.2.15" + ] + }, + "network_analysis": { + "inaccessible_subnets": [] + } + }, + "cnc": { + "servers": { + "command_servers": [ + "10.2.2.251:5000" + ], + "current_server": "10.2.2.251:5000", + "internet_services": [ + "monkey.guardicore.com", + "www.google.com" + ] + } + }, + "exploits": { + "general": { + "exploiter_classes": [ + "WmiExploiter", + "SSHExploiter", + "ShellShockExploiter", + "SambaCryExploiter", + "ElasticGroovyExploiter", + "Struts2Exploiter", + "WebLogicExploiter", + "HadoopExploiter", + "VSFTPDExploiter" + ], + "skip_exploit_if_file_exist": false + }, + "ms08_067": { + "ms08_067_exploit_attempts": 5, + "remote_user_pass": "Password1!", + "user_to_add": "Monkey_IUSER_SUPPORT" + }, + "rdp_grinder": { + "rdp_use_vbs_download": true + }, + "sambacry": { + "sambacry_folder_paths_to_guess": [ + "/", + "/mnt", + "/tmp", + "/storage", + "/export", + "/share", + "/shares", + "/home" + ], + "sambacry_shares_not_to_check": [ + "IPC$", + "print$" + ], + "sambacry_trigger_timeout": 5 + }, + "smb_service": { + "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey" + } + }, + "internal": { + "classes": { + "finger_classes": [ + "SMBFinger", + "SSHFinger", + "PingScanner", + "HTTPFinger", + "MySQLFinger", + "MSSQLFinger", + "ElasticFinger" + ] + }, + "dropper": { + "dropper_date_reference_path_linux": "/bin/sh", + "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", + "dropper_set_date": true, + "dropper_target_path_linux": "/tmp/monkey", + "dropper_target_path_win_32": "C:\\Windows\\temp\\monkey32.exe", + "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", + "dropper_try_move_first": true + }, + "exploits": { + "exploit_lm_hash_list": [], + "exploit_ntlm_hash_list": [ "f7e457346f7743daece17258667c936d" ], + "exploit_ssh_keys": [] + }, + "general": { + "keep_tunnel_open_time": 1, + "monkey_dir_name": "monkey_dir", + "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}" + }, + "kill_file": { + "kill_file_path_linux": "/var/run/monkey.not", + "kill_file_path_windows": "%windir%\\monkey.not" + }, + "logging": { + "dropper_log_path_linux": "/tmp/user-1562", + "dropper_log_path_windows": "%temp%\\~df1562.tmp", + "monkey_log_path_linux": "/tmp/user-1563", + "monkey_log_path_windows": "%temp%\\~df1563.tmp", + "send_log_to_server": true + } + }, + "monkey": { + "behaviour": { + "PBA_linux_filename": "", + "PBA_windows_filename": "", + "custom_PBA_linux_cmd": "", + "custom_PBA_windows_cmd": "", + "self_delete_in_cleanup": true, + "serialize_config": false, + "use_file_logging": true + }, + "general": { + "alive": true, + "post_breach_actions": [] + }, + "life_cycle": { + "max_iterations": 1, + "retry_failed_explotation": true, + "timeout_between_iterations": 100, + "victims_max_exploit": 7, + "victims_max_find": 30 + }, + "system_info": { + "collect_system_info": true, + "extract_azure_creds": true, + "should_use_mimikatz": true + } + }, + "network": { + "ping_scanner": { + "ping_scan_timeout": 1000 + }, + "tcp_scanner": { + "HTTP_PORTS": [ + 80, + 8080, + 443, + 8008, + 7001 + ], + "tcp_scan_get_banner": true, + "tcp_scan_interval": 0, + "tcp_scan_timeout": 3000, + "tcp_target_ports": [ + 22, + 2222, + 445, + 135, + 3389, + 80, + 8080, + 443, + 8008, + 3306, + 9200, + 7001 + ] + } + } +} diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index 4a2c7f99d..e8819b375 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -8,7 +8,7 @@ from envs.monkey_zoo.blackbox.utils import gcp_machine_handlers from envs.monkey_zoo.blackbox.tests.basic_test import BasicTest from envs.monkey_zoo.blackbox.log_handlers.test_logs_handler import TestLogsHandler -DEFAULT_TIMEOUT_SECONDS = 4*60 +DEFAULT_TIMEOUT_SECONDS = 5*60 MACHINE_BOOTUP_WAIT_SECONDS = 30 GCP_TEST_MACHINE_LIST = ['sshkeys-11', 'sshkeys-12', 'elastic-4', 'elastic-5', 'haddop-2-v3', 'hadoop-3', 'mssql-16', 'mimikatz-14', 'mimikatz-15', 'final-test-struts2-23', 'final-test-struts2-24', @@ -73,6 +73,9 @@ class TestMonkeyBlackbox(object): def test_smb_and_mimikatz_exploiters(self, island_client): TestMonkeyBlackbox.run_basic_test(island_client, "SMB_MIMIKATZ.conf", "SMB_exploiter_mimikatz") + def test_smb_pth(self, island_client): + TestMonkeyBlackbox.run_basic_test(island_client, "SMB_PTH.conf", "SMB_PTH") + def test_elastic_exploiter(self, island_client): TestMonkeyBlackbox.run_basic_test(island_client, "ELASTIC.conf", "Elastic_exploiter") @@ -86,7 +89,10 @@ class TestMonkeyBlackbox(object): TestMonkeyBlackbox.run_basic_test(island_client, "SHELLSHOCK.conf", "Shellschock_exploiter") def test_tunneling(self, island_client): - TestMonkeyBlackbox.run_basic_test(island_client, "TUNNELING.conf", "Tunneling_exploiter") + TestMonkeyBlackbox.run_basic_test(island_client, "TUNNELING.conf", "Tunneling_exploiter", 10*60) - def test_wmi_exploiter(self, island_client): + def test_wmi_and_mimikatz_exploiters(self, island_client): TestMonkeyBlackbox.run_basic_test(island_client, "WMI_MIMIKATZ.conf", "WMI_exploiter,_mimikatz") + + def test_wmi_pth(self, island_client): + TestMonkeyBlackbox.run_basic_test(island_client, "WMI_PTH.conf", "WMI_PTH") diff --git a/envs/monkey_zoo/blackbox/tests/basic_test.py b/envs/monkey_zoo/blackbox/tests/basic_test.py index 2b544a9f1..dfe0e87ee 100644 --- a/envs/monkey_zoo/blackbox/tests/basic_test.py +++ b/envs/monkey_zoo/blackbox/tests/basic_test.py @@ -5,7 +5,7 @@ from envs.monkey_zoo.blackbox.log_handlers.test_logs_handler import TestLogsHand MAX_TIME_FOR_MONKEYS_TO_DIE = 5*60 WAIT_TIME_BETWEEN_REQUESTS = 10 -TIME_FOR_MONKEY_PROCESS_TO_FINISH = 20 +TIME_FOR_MONKEY_PROCESS_TO_FINISH = 40 class BasicTest(object): From 73d434119da4d918167f7a2ce048cfcf317c2ed1 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Tue, 1 Oct 2019 10:42:51 +0300 Subject: [PATCH 22/25] CR comments fixed --- envs/monkey_zoo/blackbox/README.md | 3 +- .../island_client/monkey_island_client.py | 32 +++++++-------- .../island_client/monkey_island_requests.py | 4 +- .../blackbox/log_handlers/monkey_log.py | 3 +- .../{log_parser.py => monkey_log_parser.py} | 6 +-- ...ownloader.py => monkey_logs_downloader.py} | 8 ++-- .../log_handlers/test_logs_handler.py | 31 +++++++-------- envs/monkey_zoo/blackbox/requirements.txt | 3 +- envs/monkey_zoo/blackbox/test_blackbox.py | 18 +++++++-- envs/monkey_zoo/blackbox/tests/basic_test.py | 39 ++++++++++++------- .../blackbox/utils/gcp_machine_handlers.py | 20 +++++----- envs/monkey_zoo/blackbox/utils/test_timer.py | 2 +- monkey/infection_monkey/build_windows.bat | 2 +- monkey/infection_monkey/monkey.py | 2 + .../cc/resources/test/__init__.py | 4 ++ 15 files changed, 105 insertions(+), 72 deletions(-) rename envs/monkey_zoo/blackbox/log_handlers/{log_parser.py => monkey_log_parser.py} (80%) rename envs/monkey_zoo/blackbox/log_handlers/{logs_downloader.py => monkey_logs_downloader.py} (81%) diff --git a/envs/monkey_zoo/blackbox/README.md b/envs/monkey_zoo/blackbox/README.md index 0c66ba58a..12b33ebce 100644 --- a/envs/monkey_zoo/blackbox/README.md +++ b/envs/monkey_zoo/blackbox/README.md @@ -1,4 +1,5 @@ # Automatic blackbox tests ### Prerequisites 1. Download google sdk: https://cloud.google.com/sdk/docs/ -2. Download service account key GCP console -> IAM -> service accounts(you can use the same key used to authenticate terraform scripts) +2. Download service account key for MonkeyZoo project (if you deployed MonkeyZoo via terraform scripts then you already have it). +GCP console -> IAM -> service accounts(you can use the same key used to authenticate terraform scripts) diff --git a/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py b/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py index a06617b08..1388e0842 100644 --- a/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py +++ b/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py @@ -1,6 +1,7 @@ from time import sleep import json +import logging from bson import json_util from envs.monkey_zoo.blackbox.island_client.monkey_island_requests import MonkeyIslandRequests @@ -30,9 +31,9 @@ class MonkeyIslandClient(object): def run_monkey_local(self): response = self.requests.post_json("api/local-monkey", dict_data={"action": "run"}) if MonkeyIslandClient.monkey_ran_successfully(response): - print("Running the monkey.") + logging.info("Running the monkey.") else: - print("Failed to run the monkey.") + logging.error("Failed to run the monkey.") assert False @staticmethod @@ -42,36 +43,35 @@ class MonkeyIslandClient(object): @avoid_race_condition def kill_all_monkeys(self): if self.requests.get("api", {"action": "killall"}).ok: - print("Killing all monkeys after the test.") + logging.info("Killing all monkeys after the test.") else: - print("Failed to kill all monkeys.") + logging.error("Failed to kill all monkeys.") assert False @avoid_race_condition def reset_env(self): if self.requests.get("api", {"action": "reset"}).ok: - print("Resetting environment after the test.") + logging.info("Resetting environment after the test.") else: - print("Failed to reset the environment.") + logging.error("Failed to reset the environment.") assert False def find_monkeys_in_db(self, query): + if query is None: + raise TypeError response = self.requests.get(MONKEY_TEST_ENDPOINT, MonkeyIslandClient.form_find_query_for_request(query)) - try: - return MonkeyIslandClient.get_test_query_results(response) - except Exception: - print("Ran into trouble parsing response for monkey query") - raise + return MonkeyIslandClient.get_test_query_results(response) + + def get_all_monkeys_from_db(self): + response = self.requests.get(MONKEY_TEST_ENDPOINT, + MonkeyIslandClient.form_find_query_for_request(None)) + return MonkeyIslandClient.get_test_query_results(response) def find_log_in_db(self, query): response = self.requests.get(LOG_TEST_ENDPOINT, MonkeyIslandClient.form_find_query_for_request(query)) - try: - return MonkeyIslandClient.get_test_query_results(response) - except Exception: - print("Ran into trouble parsing response for log query") - raise + return MonkeyIslandClient.get_test_query_results(response) @staticmethod def form_find_query_for_request(query): diff --git a/envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py b/envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py index 8452f2562..5cf4d7b6a 100644 --- a/envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py +++ b/envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py @@ -1,6 +1,8 @@ import requests # SHA3-512 of '1234567890!@#$%^&*()_nothing_up_my_sleeve_1234567890!@#$%^&*()' +import logging + NO_AUTH_CREDS = '55e97c9dcfd22b8079189ddaeea9bce8125887e3237b800c6176c9afa80d2062' \ '8d2c8d0b1538d2208c1444ac66535b764a3d902b35e751df3faec1e477ed3557' @@ -14,7 +16,7 @@ class MonkeyIslandRequests(object): try: return self.get_jwt_from_server() except requests.ConnectionError: - print("Unable to connect to island, aborting!") + logging.error("Unable to connect to island, aborting!") assert False def get_jwt_from_server(self): diff --git a/envs/monkey_zoo/blackbox/log_handlers/monkey_log.py b/envs/monkey_zoo/blackbox/log_handlers/monkey_log.py index bcc304535..a0cf236fc 100644 --- a/envs/monkey_zoo/blackbox/log_handlers/monkey_log.py +++ b/envs/monkey_zoo/blackbox/log_handlers/monkey_log.py @@ -1,5 +1,6 @@ import os +import logging from bson import ObjectId @@ -11,7 +12,7 @@ class MonkeyLog(object): def download_log(self, island_client): log = island_client.find_log_in_db({'monkey_id': ObjectId(self.monkey['id'])}) if not log: - print("Log for monkey {} not found".format(self.monkey['ip_addresses'][0])) + logging.error("Log for monkey {} not found".format(self.monkey['ip_addresses'][0])) return False else: self.write_log_to_file(log) diff --git a/envs/monkey_zoo/blackbox/log_handlers/log_parser.py b/envs/monkey_zoo/blackbox/log_handlers/monkey_log_parser.py similarity index 80% rename from envs/monkey_zoo/blackbox/log_handlers/log_parser.py rename to envs/monkey_zoo/blackbox/log_handlers/monkey_log_parser.py index 9f3c34f57..d12db4f58 100644 --- a/envs/monkey_zoo/blackbox/log_handlers/log_parser.py +++ b/envs/monkey_zoo/blackbox/log_handlers/monkey_log_parser.py @@ -1,7 +1,7 @@ import re -class LogParser(object): +class MonkeyLogParser(object): def __init__(self, log_path): self.log_path = log_path @@ -13,7 +13,7 @@ class LogParser(object): def print_errors(self): print("Errors:") - for error_line in LogParser.get_errors(self.log_contents): + for error_line in MonkeyLogParser.get_errors(self.log_contents): print(error_line) @staticmethod @@ -23,7 +23,7 @@ class LogParser(object): def print_warnings(self): print("Warnings:") - for warning_line in LogParser.get_warnings(self.log_contents): + for warning_line in MonkeyLogParser.get_warnings(self.log_contents): print(warning_line) @staticmethod diff --git a/envs/monkey_zoo/blackbox/log_handlers/logs_downloader.py b/envs/monkey_zoo/blackbox/log_handlers/monkey_logs_downloader.py similarity index 81% rename from envs/monkey_zoo/blackbox/log_handlers/logs_downloader.py rename to envs/monkey_zoo/blackbox/log_handlers/monkey_logs_downloader.py index 446960147..c3bd3ac18 100644 --- a/envs/monkey_zoo/blackbox/log_handlers/logs_downloader.py +++ b/envs/monkey_zoo/blackbox/log_handlers/monkey_logs_downloader.py @@ -1,7 +1,9 @@ +import logging + from envs.monkey_zoo.blackbox.log_handlers.monkey_log import MonkeyLog -class LogsDownloader(object): +class MonkeyLogsDownloader(object): def __init__(self, island_client, log_dir_path): self.island_client = island_client @@ -9,8 +11,8 @@ class LogsDownloader(object): self.monkey_log_paths = [] def download_monkey_logs(self): - print("Downloading each monkey log.") - all_monkeys = self.island_client.find_monkeys_in_db(None) + logging.info("Downloading each monkey log.") + all_monkeys = self.island_client.get_all_monkeys_from_db() for monkey in all_monkeys: downloaded_log_path = self._download_monkey_log(monkey) if downloaded_log_path: diff --git a/envs/monkey_zoo/blackbox/log_handlers/test_logs_handler.py b/envs/monkey_zoo/blackbox/log_handlers/test_logs_handler.py index e2c87a320..6a7c2f284 100644 --- a/envs/monkey_zoo/blackbox/log_handlers/test_logs_handler.py +++ b/envs/monkey_zoo/blackbox/log_handlers/test_logs_handler.py @@ -1,28 +1,31 @@ import os import shutil -from envs.monkey_zoo.blackbox.log_handlers.log_parser import LogParser -from envs.monkey_zoo.blackbox.log_handlers.logs_downloader import LogsDownloader +import logging + +from envs.monkey_zoo.blackbox.log_handlers.monkey_log_parser import MonkeyLogParser +from envs.monkey_zoo.blackbox.log_handlers.monkey_logs_downloader import MonkeyLogsDownloader LOG_DIR_NAME = 'logs' class TestLogsHandler(object): - def __init__(self, test_name, island_client): + def __init__(self, test_name, island_client, log_dir_path): self.test_name = test_name self.island_client = island_client - self.log_dir_path = os.path.join(TestLogsHandler.get_log_dir_path(), self.test_name) + self.log_dir_path = os.path.join(log_dir_path, self.test_name) def parse_test_logs(self): log_paths = self.download_logs() if not log_paths: - print("No logs were downloaded, maybe no monkeys were ran?") + logging.error("No logs were downloaded. Maybe no monkeys were ran " + "or early exception prevented log download?") return TestLogsHandler.parse_logs(log_paths) def download_logs(self): self.try_create_log_dir_for_test() - downloader = LogsDownloader(self.island_client, self.log_dir_path) + downloader = MonkeyLogsDownloader(self.island_client, self.log_dir_path) downloader.download_monkey_logs() return downloader.monkey_log_paths @@ -30,21 +33,17 @@ class TestLogsHandler(object): try: os.mkdir(self.log_dir_path) except Exception as e: - print("Can't create a dir for test logs: {}".format(e)) + logging.error("Can't create a dir for test logs: {}".format(e)) @staticmethod - def get_log_dir_path(): - return os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), LOG_DIR_NAME) - - @staticmethod - def delete_log_folder_contents(): - shutil.rmtree(TestLogsHandler.get_log_dir_path(), ignore_errors=True) - os.mkdir(TestLogsHandler.get_log_dir_path()) + def delete_log_folder_contents(log_dir_path): + shutil.rmtree(log_dir_path, ignore_errors=True) + os.mkdir(log_dir_path) @staticmethod def parse_logs(log_paths): for log_path in log_paths: - print("Info from log at {}".format(log_path)) - log_parser = LogParser(log_path) + logging.info("Info from log at {}".format(log_path)) + log_parser = MonkeyLogParser(log_path) log_parser.print_errors() log_parser.print_warnings() diff --git a/envs/monkey_zoo/blackbox/requirements.txt b/envs/monkey_zoo/blackbox/requirements.txt index 88d363f95..c60d08124 100644 --- a/envs/monkey_zoo/blackbox/requirements.txt +++ b/envs/monkey_zoo/blackbox/requirements.txt @@ -1,2 +1,3 @@ pytest -unittest \ No newline at end of file +unittest +pytest-random-order diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index e8819b375..e9be96796 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -1,3 +1,6 @@ +import os +import logging + import pytest from time import sleep @@ -13,6 +16,7 @@ MACHINE_BOOTUP_WAIT_SECONDS = 30 GCP_TEST_MACHINE_LIST = ['sshkeys-11', 'sshkeys-12', 'elastic-4', 'elastic-5', 'haddop-2-v3', 'hadoop-3', 'mssql-16', 'mimikatz-14', 'mimikatz-15', 'final-test-struts2-23', 'final-test-struts2-24', 'tunneling-9', 'tunneling-10', 'tunneling-11', 'weblogic-18', 'weblogic-19', 'shellshock-8'] +LOG_DIR_PATH = "./logs" @pytest.fixture(autouse=True, scope='session') @@ -29,8 +33,8 @@ def GCPHandler(request): @pytest.fixture(autouse=True, scope='session') def delete_logs(): - print("Deleting monkey logs before new tests.") - TestLogsHandler.delete_log_folder_contents() + logging.info("Deleting monkey logs before new tests.") + TestLogsHandler.delete_log_folder_contents(TestMonkeyBlackbox.get_log_dir_path()) def wait_machine_bootup(): @@ -52,11 +56,17 @@ class TestMonkeyBlackbox(object): def run_basic_test(island_client, conf_filename, test_name, timeout_in_seconds=DEFAULT_TIMEOUT_SECONDS): config_parser = IslandConfigParser(conf_filename) analyzer = CommunicationAnalyzer(island_client, config_parser.get_ips_of_targets()) + log_handler = TestLogsHandler(test_name, island_client, TestMonkeyBlackbox.get_log_dir_path()) BasicTest(test_name, island_client, config_parser, [analyzer], - timeout_in_seconds).run() + timeout_in_seconds, + log_handler).run() + + @staticmethod + def get_log_dir_path(): + return os.path.abspath(LOG_DIR_PATH) def test_server_online(self, island_client): assert island_client.get_api_status() is not None @@ -75,7 +85,7 @@ class TestMonkeyBlackbox(object): def test_smb_pth(self, island_client): TestMonkeyBlackbox.run_basic_test(island_client, "SMB_PTH.conf", "SMB_PTH") - + def test_elastic_exploiter(self, island_client): TestMonkeyBlackbox.run_basic_test(island_client, "ELASTIC.conf", "Elastic_exploiter") diff --git a/envs/monkey_zoo/blackbox/tests/basic_test.py b/envs/monkey_zoo/blackbox/tests/basic_test.py index dfe0e87ee..71c53b841 100644 --- a/envs/monkey_zoo/blackbox/tests/basic_test.py +++ b/envs/monkey_zoo/blackbox/tests/basic_test.py @@ -1,21 +1,25 @@ from time import sleep +import logging + from envs.monkey_zoo.blackbox.utils.test_timer import TestTimer from envs.monkey_zoo.blackbox.log_handlers.test_logs_handler import TestLogsHandler MAX_TIME_FOR_MONKEYS_TO_DIE = 5*60 WAIT_TIME_BETWEEN_REQUESTS = 10 TIME_FOR_MONKEY_PROCESS_TO_FINISH = 40 +DELAY_BETWEEN_ANALYSIS = 3 class BasicTest(object): - def __init__(self, name, island_client, config_parser, analyzers, timeout): + def __init__(self, name, island_client, config_parser, analyzers, timeout, log_handler): self.name = name self.island_client = island_client self.config_parser = config_parser self.analyzers = analyzers self.timeout = timeout + self.log_handler = log_handler def run(self): self.island_client.import_config(self.config_parser.config_raw) @@ -31,29 +35,29 @@ class BasicTest(object): self.island_client.reset_env() def print_test_starting_info(self): - print("Started {} test".format(self.name)) - print("Machines participating in test:") - for target_ip in self.config_parser.get_ips_of_targets(): - print(" "+target_ip) - print("") + logging.info("Started {} test".format(self.name)) + logging.info("Machines participating in test:") + logging.info(" ".join(self.config_parser.get_ips_of_targets())) + logging.info("") def test_until_timeout(self): timer = TestTimer(self.timeout) - while not timer.timed_out(): + while not timer.is_timed_out(): if self.all_analyzers_pass(): self.log_success(timer) return + sleep(DELAY_BETWEEN_ANALYSIS) self.log_failure(timer) assert False def log_success(self, timer): - print(self.get_analyzer_logs()) - print("{} test passed, time taken: {:.1f} seconds.".format(self.name, timer.get_time_taken())) + logging.info(self.get_analyzer_logs()) + logging.info("{} test passed, time taken: {:.1f} seconds.".format(self.name, timer.get_time_taken())) def log_failure(self, timer): - print(self.get_analyzer_logs()) - print("{} test failed because of timeout. Time taken: {:.1f} seconds.".format(self.name, - timer.get_time_taken())) + logging.info(self.get_analyzer_logs()) + logging.error("{} test failed because of timeout. Time taken: {:.1f} seconds.".format(self.name, + timer.get_time_taken())) def all_analyzers_pass(self): for analyzer in self.analyzers: @@ -73,13 +77,18 @@ class BasicTest(object): sleep(WAIT_TIME_BETWEEN_REQUESTS) time_passed += WAIT_TIME_BETWEEN_REQUESTS if time_passed > MAX_TIME_FOR_MONKEYS_TO_DIE: - print("Some monkeys didn't die after the test, passing") + logging.error("Some monkeys didn't die after the test, failing") assert False def parse_logs(self): - print("\nParsing test logs:") - TestLogsHandler(self.name, self.island_client).parse_test_logs() + logging.info("\nParsing test logs:") + self.log_handler.parse_test_logs() @staticmethod def wait_for_monkey_process_to_finish(): + """ + There is a time period when monkey is set to dead, but the process is still closing. + If we try to launch monkey during that time window monkey will fail to start, that's + why test needs to wait a bit even after all monkeys are dead. + """ sleep(TIME_FOR_MONKEY_PROCESS_TO_FINISH) diff --git a/envs/monkey_zoo/blackbox/utils/gcp_machine_handlers.py b/envs/monkey_zoo/blackbox/utils/gcp_machine_handlers.py index 3d6e75bf4..cba6c8235 100644 --- a/envs/monkey_zoo/blackbox/utils/gcp_machine_handlers.py +++ b/envs/monkey_zoo/blackbox/utils/gcp_machine_handlers.py @@ -1,5 +1,7 @@ import subprocess +import logging + class GCPHandler(object): @@ -13,28 +15,28 @@ class GCPHandler(object): try: # pass the key file to gcp subprocess.call(GCPHandler.get_auth_command(key_path), shell=True) - print("GCP Handler passed key") + logging.info("GCP Handler passed key") # set project subprocess.call(GCPHandler.get_set_project_command(project_id), shell=True) - print("GCP Handler set project") - print("GCP Handler initialized successfully") + logging.info("GCP Handler set project") + logging.info("GCP Handler initialized successfully") except Exception as e: - print("GCP Handler failed to initialize: %s." % e) + logging.error("GCP Handler failed to initialize: %s." % e) def start_machines(self, machine_list): - print("Setting up all GCP machines...") + logging.info("Setting up all GCP machines...") try: subprocess.call((GCPHandler.MACHINE_STARTING_COMMAND % (machine_list, self.zone)), shell=True) - print("GCP machines successfully started.") + logging.info("GCP machines successfully started.") except Exception as e: - print("GCP Handler failed to start GCP machines: %s" % e) + logging.error("GCP Handler failed to start GCP machines: %s" % e) def stop_machines(self, machine_list): try: subprocess.call((GCPHandler.MACHINE_STOPPING_COMMAND % (machine_list, self.zone)), shell=True) - print("GCP machines stopped successfully.") + logging.info("GCP machines stopped successfully.") except Exception as e: - print("GCP Handler failed to stop network machines: %s" % e) + logging.error("GCP Handler failed to stop network machines: %s" % e) @staticmethod def get_auth_command(key_path): diff --git a/envs/monkey_zoo/blackbox/utils/test_timer.py b/envs/monkey_zoo/blackbox/utils/test_timer.py index c403d8a35..2c0ca490a 100644 --- a/envs/monkey_zoo/blackbox/utils/test_timer.py +++ b/envs/monkey_zoo/blackbox/utils/test_timer.py @@ -6,7 +6,7 @@ class TestTimer(object): self.timeout_time = TestTimer.get_timeout_time(timeout) self.start_time = time() - def timed_out(self): + def is_timed_out(self): return time() > self.timeout_time def get_time_taken(self): diff --git a/monkey/infection_monkey/build_windows.bat b/monkey/infection_monkey/build_windows.bat index e5ff5a805..fb12f2c0e 100644 --- a/monkey/infection_monkey/build_windows.bat +++ b/monkey/infection_monkey/build_windows.bat @@ -1 +1 @@ -pyinstaller -F --log-level=DEBUG --clean --upx-dir=.\bin monkey.spec \ No newline at end of file +C:\Programos\Python27\Scripts\pyinstaller.exe -F --log-level=DEBUG --clean --upx-dir=.\bin monkey.spec \ No newline at end of file diff --git a/monkey/infection_monkey/monkey.py b/monkey/infection_monkey/monkey.py index cd8df4705..11c0cf636 100644 --- a/monkey/infection_monkey/monkey.py +++ b/monkey/infection_monkey/monkey.py @@ -90,6 +90,8 @@ class InfectionMonkey(object): return self.set_default_port() + fbts + # Create a dir for monkey files if there isn't one utils.create_monkey_dir() diff --git a/monkey/monkey_island/cc/resources/test/__init__.py b/monkey/monkey_island/cc/resources/test/__init__.py index e69de29bb..28550f830 100644 --- a/monkey/monkey_island/cc/resources/test/__init__.py +++ b/monkey/monkey_island/cc/resources/test/__init__.py @@ -0,0 +1,4 @@ +""" +This package contains resources used by blackbox tests +to analize test results, download logs and so on. +""" From f9628940389a002ac98a5041a05fdf350ef4eeeb Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Tue, 1 Oct 2019 16:11:53 +0300 Subject: [PATCH 23/25] Real time logging implemented --- .../island_client/monkey_island_client.py | 13 +++++---- .../island_client/monkey_island_requests.py | 3 +- .../blackbox/log_handlers/monkey_log.py | 4 ++- .../log_handlers/monkey_logs_downloader.py | 4 ++- .../log_handlers/test_logs_handler.py | 9 +++--- envs/monkey_zoo/blackbox/pytest.ini | 5 ++++ envs/monkey_zoo/blackbox/test_blackbox.py | 3 +- envs/monkey_zoo/blackbox/tests/basic_test.py | 28 +++++++++---------- .../blackbox/utils/gcp_machine_handlers.py | 20 +++++++------ 9 files changed, 52 insertions(+), 37 deletions(-) create mode 100644 envs/monkey_zoo/blackbox/pytest.ini diff --git a/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py b/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py index 1388e0842..479c41bab 100644 --- a/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py +++ b/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py @@ -9,6 +9,7 @@ from envs.monkey_zoo.blackbox.island_client.monkey_island_requests import Monkey SLEEP_BETWEEN_REQUESTS_SECONDS = 0.5 MONKEY_TEST_ENDPOINT = 'api/test/monkey' LOG_TEST_ENDPOINT = 'api/test/log' +LOGGER = logging.getLogger(__name__) def avoid_race_condition(func): @@ -31,9 +32,9 @@ class MonkeyIslandClient(object): def run_monkey_local(self): response = self.requests.post_json("api/local-monkey", dict_data={"action": "run"}) if MonkeyIslandClient.monkey_ran_successfully(response): - logging.info("Running the monkey.") + LOGGER.info("Running the monkey.") else: - logging.error("Failed to run the monkey.") + LOGGER.error("Failed to run the monkey.") assert False @staticmethod @@ -43,17 +44,17 @@ class MonkeyIslandClient(object): @avoid_race_condition def kill_all_monkeys(self): if self.requests.get("api", {"action": "killall"}).ok: - logging.info("Killing all monkeys after the test.") + LOGGER.info("Killing all monkeys after the test.") else: - logging.error("Failed to kill all monkeys.") + LOGGER.error("Failed to kill all monkeys.") assert False @avoid_race_condition def reset_env(self): if self.requests.get("api", {"action": "reset"}).ok: - logging.info("Resetting environment after the test.") + LOGGER.info("Resetting environment after the test.") else: - logging.error("Failed to reset the environment.") + LOGGER.error("Failed to reset the environment.") assert False def find_monkeys_in_db(self, query): diff --git a/envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py b/envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py index 5cf4d7b6a..1f9fc2642 100644 --- a/envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py +++ b/envs/monkey_zoo/blackbox/island_client/monkey_island_requests.py @@ -5,6 +5,7 @@ import logging NO_AUTH_CREDS = '55e97c9dcfd22b8079189ddaeea9bce8125887e3237b800c6176c9afa80d2062' \ '8d2c8d0b1538d2208c1444ac66535b764a3d902b35e751df3faec1e477ed3557' +LOGGER = logging.getLogger(__name__) class MonkeyIslandRequests(object): @@ -16,7 +17,7 @@ class MonkeyIslandRequests(object): try: return self.get_jwt_from_server() except requests.ConnectionError: - logging.error("Unable to connect to island, aborting!") + LOGGER.error("Unable to connect to island, aborting!") assert False def get_jwt_from_server(self): diff --git a/envs/monkey_zoo/blackbox/log_handlers/monkey_log.py b/envs/monkey_zoo/blackbox/log_handlers/monkey_log.py index a0cf236fc..091be570a 100644 --- a/envs/monkey_zoo/blackbox/log_handlers/monkey_log.py +++ b/envs/monkey_zoo/blackbox/log_handlers/monkey_log.py @@ -3,6 +3,8 @@ import os import logging from bson import ObjectId +LOGGER = logging.getLogger(__name__) + class MonkeyLog(object): def __init__(self, monkey, log_dir_path): @@ -12,7 +14,7 @@ class MonkeyLog(object): def download_log(self, island_client): log = island_client.find_log_in_db({'monkey_id': ObjectId(self.monkey['id'])}) if not log: - logging.error("Log for monkey {} not found".format(self.monkey['ip_addresses'][0])) + LOGGER.error("Log for monkey {} not found".format(self.monkey['ip_addresses'][0])) return False else: self.write_log_to_file(log) diff --git a/envs/monkey_zoo/blackbox/log_handlers/monkey_logs_downloader.py b/envs/monkey_zoo/blackbox/log_handlers/monkey_logs_downloader.py index c3bd3ac18..dbed46780 100644 --- a/envs/monkey_zoo/blackbox/log_handlers/monkey_logs_downloader.py +++ b/envs/monkey_zoo/blackbox/log_handlers/monkey_logs_downloader.py @@ -2,6 +2,8 @@ import logging from envs.monkey_zoo.blackbox.log_handlers.monkey_log import MonkeyLog +LOGGER = logging.getLogger(__name__) + class MonkeyLogsDownloader(object): @@ -11,7 +13,7 @@ class MonkeyLogsDownloader(object): self.monkey_log_paths = [] def download_monkey_logs(self): - logging.info("Downloading each monkey log.") + LOGGER.info("Downloading each monkey log.") all_monkeys = self.island_client.get_all_monkeys_from_db() for monkey in all_monkeys: downloaded_log_path = self._download_monkey_log(monkey) diff --git a/envs/monkey_zoo/blackbox/log_handlers/test_logs_handler.py b/envs/monkey_zoo/blackbox/log_handlers/test_logs_handler.py index 6a7c2f284..fb1c39ac2 100644 --- a/envs/monkey_zoo/blackbox/log_handlers/test_logs_handler.py +++ b/envs/monkey_zoo/blackbox/log_handlers/test_logs_handler.py @@ -7,6 +7,7 @@ from envs.monkey_zoo.blackbox.log_handlers.monkey_log_parser import MonkeyLogPar from envs.monkey_zoo.blackbox.log_handlers.monkey_logs_downloader import MonkeyLogsDownloader LOG_DIR_NAME = 'logs' +LOGGER = logging.getLogger(__name__) class TestLogsHandler(object): @@ -18,8 +19,8 @@ class TestLogsHandler(object): def parse_test_logs(self): log_paths = self.download_logs() if not log_paths: - logging.error("No logs were downloaded. Maybe no monkeys were ran " - "or early exception prevented log download?") + LOGGER.error("No logs were downloaded. Maybe no monkeys were ran " + "or early exception prevented log download?") return TestLogsHandler.parse_logs(log_paths) @@ -33,7 +34,7 @@ class TestLogsHandler(object): try: os.mkdir(self.log_dir_path) except Exception as e: - logging.error("Can't create a dir for test logs: {}".format(e)) + LOGGER.error("Can't create a dir for test logs: {}".format(e)) @staticmethod def delete_log_folder_contents(log_dir_path): @@ -43,7 +44,7 @@ class TestLogsHandler(object): @staticmethod def parse_logs(log_paths): for log_path in log_paths: - logging.info("Info from log at {}".format(log_path)) + print("Info from log at {}".format(log_path)) log_parser = MonkeyLogParser(log_path) log_parser.print_errors() log_parser.print_warnings() diff --git a/envs/monkey_zoo/blackbox/pytest.ini b/envs/monkey_zoo/blackbox/pytest.ini new file mode 100644 index 000000000..79a6b4a32 --- /dev/null +++ b/envs/monkey_zoo/blackbox/pytest.ini @@ -0,0 +1,5 @@ +[pytest] +log_cli = 1 +log_cli_level = INFO +log_cli_format = %(asctime)s [%(levelname)s] %(message)s +log_cli_date_format=%H:%M:%S diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index e9be96796..4ce4603aa 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -17,6 +17,7 @@ GCP_TEST_MACHINE_LIST = ['sshkeys-11', 'sshkeys-12', 'elastic-4', 'elastic-5', ' 'mimikatz-14', 'mimikatz-15', 'final-test-struts2-23', 'final-test-struts2-24', 'tunneling-9', 'tunneling-10', 'tunneling-11', 'weblogic-18', 'weblogic-19', 'shellshock-8'] LOG_DIR_PATH = "./logs" +LOGGER = logging.getLogger(__name__) @pytest.fixture(autouse=True, scope='session') @@ -33,7 +34,7 @@ def GCPHandler(request): @pytest.fixture(autouse=True, scope='session') def delete_logs(): - logging.info("Deleting monkey logs before new tests.") + LOGGER.info("Deleting monkey logs before new tests.") TestLogsHandler.delete_log_folder_contents(TestMonkeyBlackbox.get_log_dir_path()) diff --git a/envs/monkey_zoo/blackbox/tests/basic_test.py b/envs/monkey_zoo/blackbox/tests/basic_test.py index 71c53b841..8e9066a8a 100644 --- a/envs/monkey_zoo/blackbox/tests/basic_test.py +++ b/envs/monkey_zoo/blackbox/tests/basic_test.py @@ -3,12 +3,12 @@ from time import sleep import logging from envs.monkey_zoo.blackbox.utils.test_timer import TestTimer -from envs.monkey_zoo.blackbox.log_handlers.test_logs_handler import TestLogsHandler -MAX_TIME_FOR_MONKEYS_TO_DIE = 5*60 +MAX_TIME_FOR_MONKEYS_TO_DIE = 5 * 60 WAIT_TIME_BETWEEN_REQUESTS = 10 TIME_FOR_MONKEY_PROCESS_TO_FINISH = 40 DELAY_BETWEEN_ANALYSIS = 3 +LOGGER = logging.getLogger(__name__) class BasicTest(object): @@ -35,10 +35,10 @@ class BasicTest(object): self.island_client.reset_env() def print_test_starting_info(self): - logging.info("Started {} test".format(self.name)) - logging.info("Machines participating in test:") - logging.info(" ".join(self.config_parser.get_ips_of_targets())) - logging.info("") + LOGGER.info("Started {} test".format(self.name)) + LOGGER.info("Machines participating in test:") + LOGGER.info(" ".join(self.config_parser.get_ips_of_targets())) + print("") def test_until_timeout(self): timer = TestTimer(self.timeout) @@ -51,13 +51,13 @@ class BasicTest(object): assert False def log_success(self, timer): - logging.info(self.get_analyzer_logs()) - logging.info("{} test passed, time taken: {:.1f} seconds.".format(self.name, timer.get_time_taken())) + LOGGER.info(self.get_analyzer_logs()) + LOGGER.info("{} test passed, time taken: {:.1f} seconds.".format(self.name, timer.get_time_taken())) def log_failure(self, timer): - logging.info(self.get_analyzer_logs()) - logging.error("{} test failed because of timeout. Time taken: {:.1f} seconds.".format(self.name, - timer.get_time_taken())) + LOGGER.info(self.get_analyzer_logs()) + LOGGER.error("{} test failed because of timeout. Time taken: {:.1f} seconds.".format(self.name, + timer.get_time_taken())) def all_analyzers_pass(self): for analyzer in self.analyzers: @@ -68,7 +68,7 @@ class BasicTest(object): def get_analyzer_logs(self): log = "" for analyzer in self.analyzers: - log += "\n"+analyzer.log.get_contents() + log += "\n" + analyzer.log.get_contents() return log def wait_until_monkeys_die(self): @@ -77,11 +77,11 @@ class BasicTest(object): sleep(WAIT_TIME_BETWEEN_REQUESTS) time_passed += WAIT_TIME_BETWEEN_REQUESTS if time_passed > MAX_TIME_FOR_MONKEYS_TO_DIE: - logging.error("Some monkeys didn't die after the test, failing") + LOGGER.error("Some monkeys didn't die after the test, failing") assert False def parse_logs(self): - logging.info("\nParsing test logs:") + LOGGER.info("\nParsing test logs:") self.log_handler.parse_test_logs() @staticmethod diff --git a/envs/monkey_zoo/blackbox/utils/gcp_machine_handlers.py b/envs/monkey_zoo/blackbox/utils/gcp_machine_handlers.py index cba6c8235..ac9e63d3e 100644 --- a/envs/monkey_zoo/blackbox/utils/gcp_machine_handlers.py +++ b/envs/monkey_zoo/blackbox/utils/gcp_machine_handlers.py @@ -2,6 +2,8 @@ import subprocess import logging +LOGGER = logging.getLogger(__name__) + class GCPHandler(object): @@ -15,28 +17,28 @@ class GCPHandler(object): try: # pass the key file to gcp subprocess.call(GCPHandler.get_auth_command(key_path), shell=True) - logging.info("GCP Handler passed key") + LOGGER.info("GCP Handler passed key") # set project subprocess.call(GCPHandler.get_set_project_command(project_id), shell=True) - logging.info("GCP Handler set project") - logging.info("GCP Handler initialized successfully") + LOGGER.info("GCP Handler set project") + LOGGER.info("GCP Handler initialized successfully") except Exception as e: - logging.error("GCP Handler failed to initialize: %s." % e) + LOGGER.error("GCP Handler failed to initialize: %s." % e) def start_machines(self, machine_list): - logging.info("Setting up all GCP machines...") + LOGGER.info("Setting up all GCP machines...") try: subprocess.call((GCPHandler.MACHINE_STARTING_COMMAND % (machine_list, self.zone)), shell=True) - logging.info("GCP machines successfully started.") + LOGGER.info("GCP machines successfully started.") except Exception as e: - logging.error("GCP Handler failed to start GCP machines: %s" % e) + LOGGER.error("GCP Handler failed to start GCP machines: %s" % e) def stop_machines(self, machine_list): try: subprocess.call((GCPHandler.MACHINE_STOPPING_COMMAND % (machine_list, self.zone)), shell=True) - logging.info("GCP machines stopped successfully.") + LOGGER.info("GCP machines stopped successfully.") except Exception as e: - logging.error("GCP Handler failed to stop network machines: %s" % e) + LOGGER.error("GCP Handler failed to stop network machines: %s" % e) @staticmethod def get_auth_command(key_path): From b58055d21ba8a0188a240c8a29b30b17b71a4bbf Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Thu, 3 Oct 2019 10:08:07 +0300 Subject: [PATCH 24/25] Fixed intentional bug, used for testing --- monkey/infection_monkey/monkey.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/monkey/infection_monkey/monkey.py b/monkey/infection_monkey/monkey.py index 5659b27d2..a4c72c439 100644 --- a/monkey/infection_monkey/monkey.py +++ b/monkey/infection_monkey/monkey.py @@ -93,8 +93,6 @@ class InfectionMonkey(object): return self.set_default_port() - fbts - # Create a dir for monkey files if there isn't one create_monkey_dir() From 3a02dd97e10a806bacf2aeb22a6163067abc67f4 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Thu, 3 Oct 2019 15:43:18 +0300 Subject: [PATCH 25/25] Removed unused package requirement --- envs/monkey_zoo/blackbox/requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/envs/monkey_zoo/blackbox/requirements.txt b/envs/monkey_zoo/blackbox/requirements.txt index c60d08124..0e6bd0ea3 100644 --- a/envs/monkey_zoo/blackbox/requirements.txt +++ b/envs/monkey_zoo/blackbox/requirements.txt @@ -1,3 +1,2 @@ pytest unittest -pytest-random-order