def connect(self): inventory = Inventory() address = self.hostname if inventory.has_option(self.hostname, 'address'): address = inventory.get(self.hostname, 'address') ip = None nb_name = None try: socket.inet_aton(address) ip = address except OSError as e: nb_name = address nb = NetBIOS() if ip is not None and nb_name is None: # need to look up the hostname logger.debug('Looking up NetBIOS name from IP ' + ip) nb_names = nb.queryIPForName(ip) if nb_names is None or len(nb_names) < 1: raise RuntimeError('Cannot connect to host ' + self.hostname + '; looking up NetBIOS name failed') nb_name = nb_names[0] elif ip is None and nb_name is not None: # not a IPv4 address, need to look up the ip nb_name = address logger.debug('Looking up NetBIOS IP from name ' + nb_name) ips = nb.queryName(nb_name) if ips is None or len(ips) < 1: raise RuntimeError('Cannot connect to host ' + self.hostname + '; looking up NetBIOS IP failed') ip = ips[0] nb.close() if inventory.has_option(self.hostname, 'username') and inventory.has_option( self.hostname, 'password'): username = inventory.get(self.hostname, 'username') password = inventory.get(self.hostname, 'password') client_machine_name = ''.join( random.choice(string.ascii_letters + string.digits) for _ in range(15)) logger.debug('Using client name of ' + client_machine_name) logger.info('Connecting to ' + nb_name + ' as ' + username + ' for host ' + self.hostname) self.connection = SMBHost(username, password, client_machine_name, nb_name, use_ntlm_v2=True, sign_options=SMBHost.SIGN_WHEN_SUPPORTED ) #, is_direct_tcp=True) if not self.connection.connect(ip): raise RuntimeError('Cannot connect to host ' + self.hostname + '; connecting via SMB failed') else: raise RuntimeError('No method of authenticating with host ' + self.hostname + ' found') print(str(self.connection.listPath('ADMIN$', '\\')))
def exec_command(self, cmd, sudo=False, enable=False): inventory = Inventory() if sudo: if not self.sudo_password: if not inventory.has_option(self.hostname, 'sudo_password'): self.sudo_password = getpass.getpass('Sudo password for host ' + self.hostname + ': ') else: self.sudo_password = inventory.get(self.hostname, 'sudo_password') cmd = 'sudo -S -- sh -c "' + cmd.replace('"', r'\"') + '"' # TODO need to do platform detection for sudo prompt #if sys.platform.startswith('linux'): self.sudo_prompt = '[sudo]' #elif sys.platform.startswith('darwin'): # self.sudo_prompt = 'Password:'******'sudo prompt unknown for platform ' + sys.platform) elif enable: if not self.enable_password: if not inventory.has_option(self.hostname, 'enable_password'): self.enable_password = getpass.getpass('Enable password for host ' + self.hostname + ': ') else: self.enable_password = inventory.get(self.hostname, 'enable_password') else: cmd = 'sh -c "' + cmd.replace('"', r'\"') + '"' logger.debug("Sending command: " + cmd) chan = self.client.get_transport().open_session() chan.exec_command(cmd) chan.settimeout(self.SSH_TIMEOUT) self.out_buf = '' self.err_buf = '' while True: if chan.recv_ready(): self._recv(chan) if chan.recv_stderr_ready(): self._recv_stderr(chan, sudo) if chan.exit_status_ready(): self._recv(chan) self._recv_stderr(chan, sudo) break chan.close() lines = str.splitlines(self.out_buf) for i in range(len(lines)): lines[i] = lines[i].strip() err_lines = str.splitlines(self.err_buf) for i in range(len(err_lines)): err_lines[i] = err_lines[i].strip() if len(err_lines) > 0: raise RuntimeError(str(err_lines)) return lines
def load(hostname): inventory = Inventory() # TODO better connection detection if not inventory.has_section(hostname) or not inventory.has_option( hostname, 'connection'): if hostname == 'localhost': connection_type = 'local' else: connection_type = 'ssh' else: connection_type = inventory.get(hostname, 'connection') # TODO impacket # TODO SMB? # TODO PSExec? if connection_type == 'ssh': from scap.host.cli.SSHHost import SSHHost return SSHHost(hostname) elif connection_type == 'winrm': if not inventory.has_option(hostname, 'winrm_auth_method'): raise RuntimeError( 'Host ' + hostname + ' has not specified option: winrm_auth_method') auth_method = inventory.get(hostname, 'winrm_auth_method') logger.debug('Using winrm_auth_method ' + auth_method) if auth_method == 'ssl': from scap.host.cli.winrm.WinRMHostSSL import WinRMHostSSL return WinRMHostSSL(hostname) elif auth_method == 'ntlm': from scap.host.cli.winrm.WinRMHostNTLM import WinRMHostNTLM return WinRMHostNTLM(hostname) elif auth_method == 'kerberos': from scap.host.cli.winrm.WinRMHostKerberos import WinRMHostKerberos return WinRMHostKerberos(hostname) elif auth_method == 'plaintext': from scap.host.cli.winrm.WinRMHostPlaintext import WinRMHostPlaintext return WinRMHostPlaintext(hostname) else: raise RuntimeError( 'Host ' + hostname + ' specified an invalid winrm_auth_method option') elif connection_type == 'local': if sys.platform.startswith('linux'): from scap.host.cli.local.LinuxLocalHost import LinuxLocalHost return LinuxLocalHost(hostname) elif sys.platform == 'win32': from scap.host.cli.local.WindowsLocalHost import WindowsLocalHost return WindowsLocalHost(hostname) else: raise NotImplementedError('Local connection on ' + sys.platform + ' is not yet supported') else: raise RuntimeError('Unsupported host connection type: ' + connection_type)
def connect(self): self.client = paramiko.client.SSHClient() self.client.load_system_host_keys() try: # TODO windows/linux home instead of ~ logger.debug('Read ssh host keys from ~/.pyscap/ssh_host_keys') self.client.load_host_keys(os.path.expanduser('~/.pyscap/ssh_host_keys')) except: logger.warning("Couldn't read ssh host keys") self.client.set_missing_host_key_policy(self.AskHostKeyPolicy()) inventory = Inventory() if inventory.has_option(self.hostname, 'ssh_port'): port = inventory.get(self.hostname, 'ssh_port') else: port = 22 self.sudo_password = None if inventory.has_option(self.hostname, 'ssh_username') and inventory.has_option(self.hostname, 'ssh_password'): self.client.connect(self.hostname, port=port, username=inventory.get(self.hostname, 'ssh_username'), password=inventory.get(self.hostname, 'ssh_password')) if inventory.has_option(self.hostname, 'sudo_password'): self.sudo_password = inventory.get(self.hostname, 'sudo_password') else: self.sudo_password = inventory.get(self.hostname, 'ssh_password') elif inventory.has_option(self.hostname, 'ssh_private_key_filename'): if inventory.has_option(self.hostname, 'ssh_private_key_file_password'): self.client.connect(self.hostname, port=port, key_filename=inventory.get(self.hostname, 'ssh_private_key_filename'), password=inventory.get(self.hostname, 'ssh_private_key_file_password')) else: try: self.client.connect(self.hostname, port=port, key_filename=inventory.get(self.hostname, 'ssh_private_key_filename')) except PasswordRequiredException: # retry with password ssh_private_key_file_password = getpass.getpass('Password for private key file ' + inventory.get(self.hostname, 'ssh_private_key_filename') + ': ') self.client.connect(self.hostname, port=port, key_filename=inventory.get(self.hostname, 'ssh_private_key_filename'), password=ssh_private_key_file_password) else: ssh_username = input('Username for host ' + self.hostname + ': ') if ssh_username.strip() == '': raise RuntimeError('No method of authenticating with host ' + self.hostname + ' found') ssh_password = getpass.getpass('Password for host ' + self.hostname + ': ') if inventory.has_option(self.hostname, 'sudo_password'): self.sudo_password = inventory.get(self.hostname, 'sudo_password') else: self.sudo_password = ssh_password self.client.connect(self.hostname, port=port, username=ssh_username, password=ssh_password)
def load(hostname): inventory = Inventory() # TODO better connection detection if not inventory.has_section(hostname) or not inventory.has_option(hostname, 'connection'): if hostname == 'localhost': connection_type = 'local' else: connection_type = 'ssh' else: connection_type = inventory.get(hostname, 'connection') # TODO impacket # TODO SMB? # TODO PSExec? if connection_type == 'ssh': from scap.host.cli.SSHHost import SSHHost return SSHHost(hostname) elif connection_type == 'winrm': if not inventory.has_option(hostname, 'winrm_auth_method'): raise RuntimeError('Host ' + hostname + ' has not specified option: winrm_auth_method') auth_method = inventory.get(hostname, 'winrm_auth_method') logger.debug('Using winrm_auth_method ' + auth_method) if auth_method == 'ssl': from scap.host.cli.winrm.WinRMHostSSL import WinRMHostSSL return WinRMHostSSL(hostname) elif auth_method == 'ntlm': from scap.host.cli.winrm.WinRMHostNTLM import WinRMHostNTLM return WinRMHostNTLM(hostname) elif auth_method == 'kerberos': from scap.host.cli.winrm.WinRMHostKerberos import WinRMHostKerberos return WinRMHostKerberos(hostname) elif auth_method == 'plaintext': from scap.host.cli.winrm.WinRMHostPlaintext import WinRMHostPlaintext return WinRMHostPlaintext(hostname) else: raise RuntimeError('Host ' + hostname + ' specified an invalid winrm_auth_method option') elif connection_type == 'local': if sys.platform.startswith('linux'): from scap.host.cli.local.LinuxLocalHost import LinuxLocalHost return LinuxLocalHost(hostname) elif sys.platform == 'win32': from scap.host.cli.local.WindowsLocalHost import WindowsLocalHost return WindowsLocalHost(hostname) else: raise NotImplementedError('Local connection on ' + sys.platform + ' is not yet supported') else: raise RuntimeError('Unsupported host connection type: ' + connection_type)
def __init__(self, hostname): super(CLIHost, self).__init__(hostname) inventory = Inventory() if inventory.has_option(self.hostname, 'sudo_password'): self.sudo_password = inventory.get(self.hostname, 'sudo_password') else: self.sudo_password = None if inventory.has_option(self.hostname, 'enable_password'): self.enable_password = inventory.get(self.hostname, 'enable_password') else: self.enable_password = None self._cmd_out_buf = '' self._cmd_err_buf = ''
def connect(self): self.client = paramiko.client.SSHClient() self.client.load_system_host_keys() try: # TODO windows/linux home instead of ~ logger.debug('Read ssh host keys from ~/.pyscap/ssh_host_keys') self.client.load_host_keys(os.path.expanduser('~/.pyscap/ssh_host_keys')) except: logger.warning("Couldn't read ssh host keys") self.client.set_missing_host_key_policy(self.AskHostKeyPolicy()) inventory = Inventory() if inventory.has_option(self.hostname, 'ssh_port'): port = inventory.get(self.hostname, 'ssh_port') else: port = 22 if inventory.has_option(self.hostname, 'ssh_username') and inventory.has_option(self.hostname, 'ssh_password'): self.client.connect(self.hostname, port=port, username=inventory.get(self.hostname, 'ssh_username'), password=inventory.get(self.hostname, 'ssh_password')) elif inventory.has_option(self.hostname, 'ssh_private_key_filename'): if inventory.has_option(self.hostname, 'ssh_private_key_file_password'): self.client.connect(self.hostname, port=port, key_filename=inventory.get(self.hostname, 'ssh_private_key_filename'), password=inventory.get(self.hostname, 'ssh_private_key_file_password')) else: try: self.client.connect(self.hostname, port=port, key_filename=inventory.get(self.hostname, 'ssh_private_key_filename')) except PasswordRequiredException: # retry with password ssh_private_key_file_password = getpass.getpass('Password for private key file ' + inventory.get(self.hostname, 'ssh_private_key_filename') + ': ') self.client.connect(self.hostname, port=port, key_filename=inventory.get(self.hostname, 'ssh_private_key_filename'), password=ssh_private_key_file_password) else: ssh_username = input('Username for host ' + self.hostname + ': ') if ssh_username.strip() == '': raise RuntimeError('No method of authenticating with host ' + self.hostname + ' found') ssh_password = getpass.getpass('Password for host ' + self.hostname + ': ') self.client.connect(self.hostname, port=port, username=ssh_username, password=ssh_password) from scap.collector.UNameCollector import UNameCollector UNameCollector(self, {}).collect() if self.facts['uname']['kernel_name'] == 'Linux': self.facts['oval_family'] = 'linux' # elif uname.startswith('Darwin'): # TODO elif self.facts['uname']['kernel_name'] == 'Windows NT': self.facts['oval_family'] = 'windows' else: raise NotImplementedError('Host detection has not been implemented for uname: ' + self.facts['uname'] + ' on ' + self.hostname)
def connect(self): inventory = Inventory() if inventory.has_option(self.hostname, 'address'): address = inventory.get(self.hostname, 'address') else: address = self.hostname logger.debug('Using address ' + address) if inventory.has_option(self.hostname, 'scheme'): scheme = inventory.get(self.hostname, 'scheme') else: scheme = 'http' logger.debug('Using url scheme ' + scheme) if inventory.has_option(self.hostname, 'port'): port = inventory.get(self.hostname, 'port') else: if scheme == 'http': port = '5985' elif scheme == 'https': port = '5986' else: raise('Invalid WinRM scheme: ' + scheme) logger.debug('Using port ' + port) if not inventory.has_option(self.hostname, 'username'): raise RuntimeError('Host ' + self.hostname + ' has not specified option: username') username = inventory.get(self.hostname, 'username') if inventory.has_option(self.hostname, 'kerberos_realm'): username = username + '@' + inventory.get(self.hostname, 'kerberos_realm') logger.debug('Using username ' + username) if inventory.has_option(self.hostname, 'kerberos_delegation'): kerberos_delegation = inventory.get(self.hostname, 'kerberos_delegation') else: kerberos_delegation = False if inventory.has_option(self.hostname, 'kerberos_hostname_override'): kerberos_hostname_override = inventory.get(self.hostname, 'kerberos_hostname_override') else: kerberos_hostname_override = None self.protocol = Protocol( endpoint=scheme + '://' + address + ':' + port + '/wsman', transport='kerberos', username=username, kerberos_delegation=kerberos_delegation, kerberos_hostname_override=kerberos_hostname_override) try: self.shell_id = self.protocol.open_shell() except Exception as e: logger.warning(str(e))
def connect(self): inventory = Inventory() if inventory.has_option(self.hostname, 'address'): address = inventory.get(self.hostname, 'address') else: address = self.hostname logger.debug('Using address ' + address) if inventory.has_option(self.hostname, 'scheme'): scheme = inventory.get(self.hostname, 'scheme') else: scheme = 'http' logger.debug('Using url scheme ' + scheme) if inventory.has_option(self.hostname, 'port'): port = inventory.get(self.hostname, 'port') else: if scheme == 'http': port = '5985' elif scheme == 'https': port = '5986' else: raise ('Invalid WinRM scheme: ' + scheme) logger.debug('Using port ' + port) if not inventory.has_option(self.hostname, 'username'): raise RuntimeError('Host ' + self.hostname + ' has not specified option: username') username = inventory.get(self.hostname, 'username') if inventory.has_option(self.hostname, 'domain'): username = inventory.get(self.hostname, 'domain') + '\\' + username logger.debug('Using username ' + username) if not inventory.has_option(self.hostname, 'password'): raise RuntimeError('Host ' + self.hostname + ' has not specified option: password') password = inventory.get(self.hostname, 'password') self.protocol = Protocol(endpoint=scheme + '://' + address + ':' + port + '/wsman', transport='plaintext', username=username, password=password) try: self.shell_id = self.protocol.open_shell() except Exception as e: logger.warning(str(e))
def exec_command(self, cmd, sudo=False): inventory = Inventory() if sudo: if hasattr(self, 'sudo_password'): pass elif inventory.has_option(self.hostname, 'sudo_password'): self.sudo_password = inventory.get(self.hostname, 'sudo_password') else: self.sudo_password = getpass.getpass( 'Sudo password for host ' + self.hostname + ': ') cmd = 'sudo -S -- sh -c "' + cmd.replace('"', r'\"') + '"' if sys.platform.startswith('linux'): sudo_prompt = '[sudo]' elif sys.platform.startswith('darwin'): sudo_prompt = 'Password:'******'sudo prompt unknown for platform ' + sys.platform) logger.debug("Sending command: " + cmd) p = Popen(cmd, stdout=PIPE, stdin=PIPE, stderr=PIPE, shell=True, universal_newlines=True) # note; can't use p.communicate; have to figure out if we get a prompt # because there isn't if within sudo timeout out_buf = '' err_buf = '' sel = selectors.DefaultSelector() sel.register(p.stdout, selectors.EVENT_READ) sel.register(p.stderr, selectors.EVENT_READ) while True: ready_list = sel.select(10) if len(ready_list) == 0: # timeout p.stdin.close() break for (key, events) in ready_list: if key.fileobj is p.stdout and events & selectors.EVENT_READ: outs = p.stdout.buffer.read1(1024).decode() if len(outs) > 0: logger.debug('Got stdout: ' + outs) out_buf += outs elif key.fileobj is p.stderr and events & selectors.EVENT_READ: errs = p.stderr.buffer.read1(1024).decode() if len(errs) > 0: logger.debug('Got stderr: ' + errs) err_buf += errs if sudo and err_buf.startswith(sudo_prompt): logger.debug("Sending sudo_password...") p.stdin.write(self.sudo_password + "\n") p.stdin.close() err_buf = '' if p.stdout.closed and p.stderr.closed: p.stdin.close() p.poll() break if p.poll() is not None: p.stdin.close() break if not p.stdout.closed: outs = p.stdout.buffer.read1(1024).decode() if len(outs) > 0: logger.debug('Got extra-loop stdout: ' + outs) out_buf += outs if not p.stderr.closed: errs = p.stderr.buffer.read1(1024).decode() if len(errs) > 0: logger.debug('Got extra-loop stderr: ' + errs) err_buf += errs if sudo and err_buf.startswith(sudo_prompt): logger.debug("Sending sudo_password...") p.stdin.write(self.sudo_password + "\n") p.stdin.close() err_buf = '' sel.unregister(p.stdout) sel.unregister(p.stderr) sel.close() out_lines = str.splitlines(out_buf) out_lines = [line.strip('\x0A\x0D') for line in out_lines] err_lines = str.splitlines(err_buf) err_lines = [line.strip('\x0A\x0D') for line in err_lines] return (p.returncode, out_lines, err_lines)
def connect(self): self.client = paramiko.client.SSHClient() self.client.load_system_host_keys() try: # TODO windows/linux home instead of ~ logger.debug('Read ssh host keys from ~/.pyscap/ssh_host_keys') self.client.load_host_keys( os.path.expanduser('~/.pyscap/ssh_host_keys')) except: logger.warning("Couldn't read ssh host keys") self.client.set_missing_host_key_policy(self.AskHostKeyPolicy()) inventory = Inventory() if inventory.has_option(self.hostname, 'ssh_port'): port = inventory.get(self.hostname, 'ssh_port') else: port = 22 self.sudo_password = None if inventory.has_option(self.hostname, 'ssh_username') and inventory.has_option( self.hostname, 'ssh_password'): self.client.connect(self.hostname, port=port, username=inventory.get(self.hostname, 'ssh_username'), password=inventory.get(self.hostname, 'ssh_password')) if inventory.has_option(self.hostname, 'sudo_password'): self.sudo_password = inventory.get(self.hostname, 'sudo_password') else: self.sudo_password = inventory.get(self.hostname, 'ssh_password') elif inventory.has_option(self.hostname, 'ssh_private_key_filename'): if inventory.has_option(self.hostname, 'ssh_private_key_file_password'): self.client.connect( self.hostname, port=port, key_filename=inventory.get(self.hostname, 'ssh_private_key_filename'), password=inventory.get(self.hostname, 'ssh_private_key_file_password')) else: try: self.client.connect(self.hostname, port=port, key_filename=inventory.get( self.hostname, 'ssh_private_key_filename')) except PasswordRequiredException: # retry with password ssh_private_key_file_password = getpass.getpass( 'Password for private key file ' + inventory.get( self.hostname, 'ssh_private_key_filename') + ': ') self.client.connect(self.hostname, port=port, key_filename=inventory.get( self.hostname, 'ssh_private_key_filename'), password=ssh_private_key_file_password) else: ssh_username = input('Username for host ' + self.hostname + ': ') if ssh_username.strip() == '': raise RuntimeError('No method of authenticating with host ' + self.hostname + ' found') ssh_password = getpass.getpass('Password for host ' + self.hostname + ': ') if inventory.has_option(self.hostname, 'sudo_password'): self.sudo_password = inventory.get(self.hostname, 'sudo_password') else: self.sudo_password = ssh_password self.client.connect(self.hostname, port=port, username=ssh_username, password=ssh_password) try: from scap.collector.UNameCollector import UNameCollector UNameCollector(self, {}).collect() except: # uname didn't work raise NotImplementedError('Unable to run uname on host: ' + self.host.hostname) if self.facts['uname'].startswith('Linux'): self.facts['oval_family'] = 'linux' # elif uname.startswith('Darwin'): # pass elif self.facts['uname'].startswith('Windows NT'): self.facts['oval_family'] = 'windows' else: raise NotImplementedError( 'Host detection has not been implemented for uname: ' + self.facts['uname'] + ' on ' + self.hostname)
def connect(self): inventory = Inventory() address = self.hostname if inventory.has_option(self.hostname, 'address'): address = inventory.get(self.hostname, 'address')