From 36b6752827a2dcc5266e4b90152523b17e3f955e Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Wed, 11 Sep 2019 12:39:28 +0300 Subject: [PATCH] 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