Got 500 from delete operation so simplyfing and re-trying
This commit is contained in:
parent
9965947d3f
commit
97976cdbc5
|
@ -1,3 +1,4 @@
|
||||||
|
import logging
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from envs.monkey_zoo.blackbox.analyzers.analyzer import Analyzer
|
from envs.monkey_zoo.blackbox.analyzers.analyzer import Analyzer
|
||||||
|
@ -7,15 +8,23 @@ from envs.monkey_zoo.blackbox.island_client.monkey_island_client import MonkeyIs
|
||||||
MAX_ALLOWED_SINGLE_PAGE_TIME = timedelta(seconds=1)
|
MAX_ALLOWED_SINGLE_PAGE_TIME = timedelta(seconds=1)
|
||||||
MAX_ALLOWED_TOTAL_TIME = timedelta(seconds=3)
|
MAX_ALLOWED_TOTAL_TIME = timedelta(seconds=3)
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PerformanceAnalyzer(Analyzer):
|
class PerformanceAnalyzer(Analyzer):
|
||||||
|
|
||||||
def __init__(self, island_client: MonkeyIslandClient):
|
def __init__(self, island_client: MonkeyIslandClient, break_if_took_too_long=False):
|
||||||
|
self.break_if_took_too_long = break_if_took_too_long
|
||||||
self.island_client = island_client
|
self.island_client = island_client
|
||||||
self.log = AnalyzerLog(self.__class__.__name__)
|
self.log = AnalyzerLog(self.__class__.__name__)
|
||||||
|
|
||||||
def analyze_test_results(self) -> bool:
|
def analyze_test_results(self) -> bool:
|
||||||
self.log.clear()
|
self.log.clear()
|
||||||
|
|
||||||
|
if not self.island_client.is_all_monkeys_dead():
|
||||||
|
self.log.add_entry("Can't test report times since not all Monkeys have died.")
|
||||||
|
return False
|
||||||
|
|
||||||
total_time = timedelta()
|
total_time = timedelta()
|
||||||
|
|
||||||
self.island_client.clear_caches()
|
self.island_client.clear_caches()
|
||||||
|
@ -33,4 +42,11 @@ class PerformanceAnalyzer(Analyzer):
|
||||||
|
|
||||||
self.log.add_entry(f"total time is {str(total_time)}")
|
self.log.add_entry(f"total time is {str(total_time)}")
|
||||||
|
|
||||||
|
if self.break_if_took_too_long and (not (total_time_less_then_max and single_page_time_less_then_max)):
|
||||||
|
logger.warning(
|
||||||
|
"Calling breakpoint - pausing to enable investigation of island. Type 'c' to continue once you're done "
|
||||||
|
"investigating. type 'p timings' and 'p total_time' to see performance information."
|
||||||
|
)
|
||||||
|
breakpoint()
|
||||||
|
|
||||||
return total_time_less_then_max and single_page_time_less_then_max
|
return total_time_less_then_max and single_page_time_less_then_max
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from datetime import timedelta
|
||||||
from time import sleep
|
from time import sleep
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
@ -109,10 +110,13 @@ class MonkeyIslandClient(object):
|
||||||
|
|
||||||
for url in REPORT_URLS:
|
for url in REPORT_URLS:
|
||||||
response = self.requests.get(url)
|
response = self.requests.get(url)
|
||||||
if response:
|
if response.ok:
|
||||||
|
LOGGER.debug(f"Got ok for {url} content peek:\n{response.content[:120]}")
|
||||||
report_resource_to_response_time[url] = response.elapsed
|
report_resource_to_response_time[url] = response.elapsed
|
||||||
else:
|
else:
|
||||||
LOGGER.error(f"Trying to get {url} but got unexpected {str(response)}")
|
LOGGER.error(f"Trying to get {url} but got unexpected {str(response)}")
|
||||||
response.raise_for_status()
|
# instead of raising for status, mark failed responses as maxtime
|
||||||
|
report_resource_to_response_time[url] = timedelta.max()
|
||||||
|
|
||||||
|
|
||||||
return report_resource_to_response_time
|
return report_resource_to_response_time
|
||||||
|
|
|
@ -0,0 +1,186 @@
|
||||||
|
{
|
||||||
|
"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.2",
|
||||||
|
"10.2.2.4"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"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": [
|
||||||
|
"SSHExploiter",
|
||||||
|
"MSSQLExploiter",
|
||||||
|
"ElasticGroovyExploiter",
|
||||||
|
"HadoopExploiter"
|
||||||
|
],
|
||||||
|
"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": 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": false,
|
||||||
|
"should_use_mimikatz": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"ping_scanner": {
|
||||||
|
"ping_scan_timeout": 500
|
||||||
|
},
|
||||||
|
"tcp_scanner": {
|
||||||
|
"HTTP_PORTS": [
|
||||||
|
80,
|
||||||
|
8080,
|
||||||
|
443,
|
||||||
|
8008,
|
||||||
|
7001
|
||||||
|
],
|
||||||
|
"tcp_scan_get_banner": true,
|
||||||
|
"tcp_scan_interval": 0,
|
||||||
|
"tcp_scan_timeout": 1000,
|
||||||
|
"tcp_target_ports": [
|
||||||
|
22,
|
||||||
|
2222,
|
||||||
|
445,
|
||||||
|
135,
|
||||||
|
3389,
|
||||||
|
80,
|
||||||
|
8080,
|
||||||
|
443,
|
||||||
|
8008,
|
||||||
|
3306,
|
||||||
|
9200,
|
||||||
|
7001
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ from envs.monkey_zoo.blackbox.tests.basic_test import BasicTest
|
||||||
from envs.monkey_zoo.blackbox.log_handlers.test_logs_handler import TestLogsHandler
|
from envs.monkey_zoo.blackbox.log_handlers.test_logs_handler import TestLogsHandler
|
||||||
|
|
||||||
DEFAULT_TIMEOUT_SECONDS = 5*60
|
DEFAULT_TIMEOUT_SECONDS = 5*60
|
||||||
|
PERFORMANCE_TIMEOUT_SECONDS = 10*60
|
||||||
MACHINE_BOOTUP_WAIT_SECONDS = 30
|
MACHINE_BOOTUP_WAIT_SECONDS = 30
|
||||||
GCP_TEST_MACHINE_LIST = ['sshkeys-11', 'sshkeys-12', 'elastic-4', 'elastic-5', 'hadoop-2', 'hadoop-3', 'mssql-16',
|
GCP_TEST_MACHINE_LIST = ['sshkeys-11', 'sshkeys-12', 'elastic-4', 'elastic-5', 'hadoop-2', 'hadoop-3', 'mssql-16',
|
||||||
'mimikatz-14', 'mimikatz-15', 'struts2-23', 'struts2-24', 'tunneling-9', 'tunneling-10',
|
'mimikatz-14', 'mimikatz-15', 'struts2-23', 'struts2-24', 'tunneling-9', 'tunneling-10',
|
||||||
|
@ -59,27 +60,30 @@ class TestMonkeyBlackbox(object):
|
||||||
config_parser = IslandConfigParser(conf_filename)
|
config_parser = IslandConfigParser(conf_filename)
|
||||||
analyzer = CommunicationAnalyzer(island_client, config_parser.get_ips_of_targets())
|
analyzer = CommunicationAnalyzer(island_client, config_parser.get_ips_of_targets())
|
||||||
log_handler = TestLogsHandler(test_name, island_client, TestMonkeyBlackbox.get_log_dir_path())
|
log_handler = TestLogsHandler(test_name, island_client, TestMonkeyBlackbox.get_log_dir_path())
|
||||||
BasicTest(test_name,
|
BasicTest(
|
||||||
island_client,
|
name=test_name,
|
||||||
config_parser,
|
island_client=island_client,
|
||||||
[analyzer],
|
config_parser=config_parser,
|
||||||
timeout_in_seconds,
|
analyzers=[analyzer],
|
||||||
log_handler).run()
|
timeout=timeout_in_seconds,
|
||||||
|
post_exec_analyzers=[],
|
||||||
|
log_handler=log_handler).run()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run_performance_test(island_client, conf_filename, test_name, timeout_in_seconds=DEFAULT_TIMEOUT_SECONDS):
|
def run_performance_test(island_client, conf_filename, test_name, timeout_in_seconds=DEFAULT_TIMEOUT_SECONDS):
|
||||||
config_parser = IslandConfigParser(conf_filename)
|
config_parser = IslandConfigParser(conf_filename)
|
||||||
analyzers = [
|
|
||||||
# TODO CommunicationAnalyzer(island_client, config_parser.get_ips_of_targets()),
|
|
||||||
PerformanceAnalyzer(island_client),
|
|
||||||
]
|
|
||||||
log_handler = TestLogsHandler(test_name, island_client, TestMonkeyBlackbox.get_log_dir_path())
|
log_handler = TestLogsHandler(test_name, island_client, TestMonkeyBlackbox.get_log_dir_path())
|
||||||
BasicTest(test_name,
|
BasicTest(
|
||||||
|
name=test_name,
|
||||||
|
island_client=island_client,
|
||||||
|
config_parser=config_parser,
|
||||||
|
analyzers=[CommunicationAnalyzer(island_client, config_parser.get_ips_of_targets())],
|
||||||
|
timeout=timeout_in_seconds,
|
||||||
|
post_exec_analyzers=[PerformanceAnalyzer(
|
||||||
island_client,
|
island_client,
|
||||||
config_parser,
|
break_if_took_too_long=True # TODO change to false before merging!!!
|
||||||
analyzers,
|
)],
|
||||||
timeout_in_seconds,
|
log_handler=log_handler).run()
|
||||||
log_handler).run()
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_log_dir_path():
|
def get_log_dir_path():
|
||||||
|
@ -126,4 +130,15 @@ class TestMonkeyBlackbox(object):
|
||||||
TestMonkeyBlackbox.run_basic_test(island_client, "WMI_PTH.conf", "WMI_PTH")
|
TestMonkeyBlackbox.run_basic_test(island_client, "WMI_PTH.conf", "WMI_PTH")
|
||||||
|
|
||||||
def test_performance(self, island_client):
|
def test_performance(self, island_client):
|
||||||
TestMonkeyBlackbox.run_performance_test(island_client, "STRUTS2.conf", "Report_timing")
|
"""
|
||||||
|
This test includes the SSH + Elastic + Hadoop + MSSQL machines all in one test
|
||||||
|
for a total of 8 machines including the Monkey Island.
|
||||||
|
|
||||||
|
Is has 2 analyzers - the regular one which checks all the Monkeys
|
||||||
|
and the Timing one which checks how long the report took to execute
|
||||||
|
"""
|
||||||
|
TestMonkeyBlackbox.run_performance_test(
|
||||||
|
island_client,
|
||||||
|
"PERFORMANCE.conf",
|
||||||
|
"test_report_performance",
|
||||||
|
timeout_in_seconds=PERFORMANCE_TIMEOUT_SECONDS)
|
||||||
|
|
|
@ -14,11 +14,12 @@ LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
class BasicTest(object):
|
class BasicTest(object):
|
||||||
|
|
||||||
def __init__(self, name, island_client, config_parser, analyzers, timeout, log_handler):
|
def __init__(self, name, island_client, config_parser, analyzers, timeout, post_exec_analyzers, log_handler):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.island_client = island_client
|
self.island_client = island_client
|
||||||
self.config_parser = config_parser
|
self.config_parser = config_parser
|
||||||
self.analyzers = analyzers
|
self.analyzers = analyzers
|
||||||
|
self.post_exec_analyzers = post_exec_analyzers
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
self.log_handler = log_handler
|
self.log_handler = log_handler
|
||||||
|
|
||||||
|
@ -32,13 +33,13 @@ class BasicTest(object):
|
||||||
self.island_client.kill_all_monkeys()
|
self.island_client.kill_all_monkeys()
|
||||||
self.wait_until_monkeys_die()
|
self.wait_until_monkeys_die()
|
||||||
self.wait_for_monkey_process_to_finish()
|
self.wait_for_monkey_process_to_finish()
|
||||||
|
self.test_post_exec_analyzers()
|
||||||
self.parse_logs()
|
self.parse_logs()
|
||||||
self.island_client.reset_env()
|
self.island_client.reset_env()
|
||||||
|
|
||||||
def print_test_starting_info(self):
|
def print_test_starting_info(self):
|
||||||
LOGGER.info("Started {} test".format(self.name))
|
LOGGER.info("Started {} test".format(self.name))
|
||||||
LOGGER.info("Machines participating in test:")
|
LOGGER.info("Machines participating in test: " + ", ".join(self.config_parser.get_ips_of_targets()))
|
||||||
LOGGER.info(" ".join(self.config_parser.get_ips_of_targets()))
|
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
def test_until_timeout(self):
|
def test_until_timeout(self):
|
||||||
|
@ -62,14 +63,12 @@ class BasicTest(object):
|
||||||
timer.get_time_taken()))
|
timer.get_time_taken()))
|
||||||
|
|
||||||
def all_analyzers_pass(self):
|
def all_analyzers_pass(self):
|
||||||
for analyzer in self.analyzers:
|
analyzers_results = [analyzer.analyze_test_results() for analyzer in self.analyzers]
|
||||||
if not analyzer.analyze_test_results():
|
return all(analyzers_results)
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def get_analyzer_logs(self):
|
def get_analyzer_logs(self):
|
||||||
log = ""
|
log = ""
|
||||||
for analyzer in self.analyzers:
|
for analyzer in self.get_all_analyzers():
|
||||||
log += "\n" + analyzer.log.get_contents()
|
log += "\n" + analyzer.log.get_contents()
|
||||||
return log
|
return log
|
||||||
|
|
||||||
|
@ -94,4 +93,12 @@ class BasicTest(object):
|
||||||
If we try to launch monkey during that time window monkey will fail to start, that's
|
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.
|
why test needs to wait a bit even after all monkeys are dead.
|
||||||
"""
|
"""
|
||||||
|
LOGGER.debug()
|
||||||
sleep(TIME_FOR_MONKEY_PROCESS_TO_FINISH)
|
sleep(TIME_FOR_MONKEY_PROCESS_TO_FINISH)
|
||||||
|
|
||||||
|
def test_post_exec_analyzers(self):
|
||||||
|
post_exec_analyzers_results = [analyzer.analyze_test_results() for analyzer in self.post_exec_analyzers]
|
||||||
|
assert all(post_exec_analyzers_results)
|
||||||
|
|
||||||
|
def get_all_analyzers(self):
|
||||||
|
return self.analyzers + self.post_exec_analyzers
|
||||||
|
|
|
@ -106,8 +106,12 @@ class AttackReportService:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def delete_saved_report_if_exists():
|
def delete_saved_report_if_exists():
|
||||||
if AttackReportService.is_report_generated():
|
delete_result = mongo.db.attack_report.delete_many({})
|
||||||
latest_report = mongo.db.attack_report.find_one({'name': REPORT_NAME})
|
if mongo.db.attack_report.count_documents({}) != 0:
|
||||||
delete_result = mongo.db.report.delete_one({"_id": latest_report['_id']})
|
raise RuntimeError("Attack Report cache not cleared. DeleteResult: " + delete_result.raw_result)
|
||||||
if delete_result.deleted_count != 1:
|
# if AttackReportService.is_report_generated():
|
||||||
raise RuntimeError("Error while deleting report:" + str(delete_result))
|
# mongo.db.attack_report.delete_many({})
|
||||||
|
# latest_report = mongo.db.attack_report.find_one({'name': REPORT_NAME})
|
||||||
|
# delete_result = mongo.db.report.delete_one({"_id": latest_report['_id']})
|
||||||
|
# if delete_result.deleted_count != 1:
|
||||||
|
# raise RuntimeError("Error while deleting report. Deleted count: " + str(delete_result.deleted_count))
|
||||||
|
|
|
@ -779,12 +779,15 @@ class ReportService:
|
||||||
This function clears the saved report from the DB.
|
This function clears the saved report from the DB.
|
||||||
:raises RuntimeError if deletion failed
|
:raises RuntimeError if deletion failed
|
||||||
"""
|
"""
|
||||||
latest_report_doc = mongo.db.report.find_one({}, {'meta.latest_monkey_modifytime': 1})
|
delete_result = mongo.db.report.delete_many({})
|
||||||
|
if mongo.db.report.count_documents({}) != 0:
|
||||||
if latest_report_doc:
|
raise RuntimeError("Report cache not cleared. DeleteResult: " + delete_result.raw_result)
|
||||||
delete_result = mongo.db.report.delete_one({"_id": latest_report_doc['_id']})
|
# latest_report_doc = mongo.db.report.find_one({}, {'meta.latest_monkey_modifytime': 1})
|
||||||
if delete_result.deleted_count != 1:
|
#
|
||||||
raise RuntimeError("Error while deleting report:" + str(delete_result))
|
# if latest_report_doc:
|
||||||
|
# delete_result = mongo.db.report.delete_one({"_id": latest_report_doc['_id']})
|
||||||
|
# if delete_result.deleted_count != 1:
|
||||||
|
# raise RuntimeError("Error while deleting report:" + str(delete_result))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def decode_dot_char_before_mongo_insert(report_dict):
|
def decode_dot_char_before_mongo_insert(report_dict):
|
||||||
|
|
Loading…
Reference in New Issue