def __init__(self, endpoint, auth, transport='ssl', validation='ignore'): username, password = auth self.protocol = winrm.Protocol(endpoint=endpoint, transport=transport, username=username, password=password, server_cert_validation=validation)
def __init__(self, target, auth, transport="ssl"): key, cert = auth self.url = self._build_url(target, transport) self.protocol = winrm.Protocol(self.url, transport=transport, cert_key_pem=key, cert_pem=cert)
def __init__(self, endpoint, auth, validation='ignore'): cert, key = auth self.protocol = winrm.Protocol(endpoint=endpoint, transport='ssl', cert_pem=cert, cert_key_pem=key, server_cert_validation=validation)
def __init__(self, endpoint, auth, target=None, target_auth=None, transport='ssl', validation='ignore'): username = auth.AccountName password = auth.passwd() self.protocol = winrm.Protocol(endpoint=endpoint, transport=transport, username=username, password=password, server_cert_validation=validation) self.target = target self.target_auth = (target_auth.WindowsUserName, target_auth.passwd())
def run_winrm(endpoint, user, password, task): remotehost = f"http://{endpoint}:5985/wsman" print(f"Remote host {remotehost}") print(f"Connecting as User {user}") pwsh = """ $PSSenderInfo | convertto-json $git=Invoke-Webrequest -Uri "https://raw.githubusercontent.com/MLSeven/Gitstuff/main/PShell/tasktools.ps1" -UseBasicParsing invoke-expression $git.content Get-TaskInfo -AsJson """ powershell_session = winrm.Session(remotehost, auth=(user, password), transport='ntlm') # force protocol to accept unsigned certs p = winrm.Protocol(endpoint=remotehost, transport='ntlm', username=user, password=password, server_cert_validation='ignore') powershell_session.protocol = p try: run_ps = powershell_session.run_ps(pwsh) except Exception as err: print(f"winRm Exception {err}") sys.exit(1) exit_code = run_ps.status_code print(f"Powershell exit code {exit_code}") error_value = run_ps.std_err output = run_ps.std_out error_value = error_value.decode('utf-8') output = output.decode('utf-8') if exit_code != 0: raise Exception( 'An error occurred in the PowerShell script, see logging for more info' ) print(len(output)) return output
def __init__(self, endpoint, auth, target=None, target_auth=None, transport='ssl', validation='ignore', **kwargs): username, password = auth self.protocol = winrm.Protocol(endpoint=endpoint, transport=transport, username=username, password=password, server_cert_validation=validation, **kwargs) self.target = target self.target_auth = target_auth
def __init__(self, endpoint, certificate, target=None, target_auth=None, validation='ignore'): self.protocol = winrm.Protocol(endpoint=endpoint, transport='certificate', server_cert_validation=validation, cert_pem=certificate, cert_key_pem=certificate) if target and target_auth: self.target = target self.target_auth = (target_auth.WindowsUserName, target_auth.passwd()) else: self.target = None self.target_auth = None
def __init__(self, address, username, password, scheme='https', port=5986, transport='plaintext'): """ Create a model of a remote windows machine params: address - the address of the remote machine i.e 8.8.8.8 or some.domain.com username - the username used to run commands on the remote machine password - the password used to run commands on the remote machine scheme - the protocol scheme used to connect to winrm currently only http and https are supported port - the port used to connect to winrm, default is 5986 transport - transport method used to connect to winrm currently only plaintext and ssl are supported returns: an object representing the remote machine raises: ValueError - one or more of the arguments passed were invalid """ scheme = scheme.lower() if scheme not in ['http', 'https']: raise ValueError transport = transport.lower() if transport not in ['ssl', 'plaintext']: raise ValueError if port < 0: raise ValueError self.endpoint = '%s://%s:%d/wsman' % (scheme, address, port) self.username = username self.password = password self.protocol = winrm.Protocol(self.endpoint, transport=transport, username=self.username, password=self.password) self.shell_id = self.protocol.open_shell()
def ntlm(action, host_ip, powershell_script, username, password, port): # Adds needed https and port number to host IP action.logger.info('Running a NTLM connection') host_connection = 'https://{host_ip}:{port}/wsman'.format(host_ip=host_ip, port=port) action.logger.debug('Host Connection: ' + host_connection) action.logger.debug('PowerShell script: ' + powershell_script) powershell_session = winrm.Session(host_connection, auth=(username, password), transport='ntlm') # Forces the Protocol to not fail with self signed certs p = winrm.Protocol(endpoint=host_connection, transport='ntlm', username=username, password=password, server_cert_validation='ignore', message_encryption='auto') powershell_session.protocol = p run_script = powershell_session.run_ps(powershell_script) exit_code = run_script.status_code error_value = run_script.std_err output = run_script.std_out try: error_value = error_value.decode('utf-8') except AttributeError: pass output = output.decode('utf-8') if exit_code != 0: action.logger.error(error_value) raise Exception( 'An error occurred in the PowerShell script, see logging for more info' ) return {'output': output, 'stderr': error_value}
def __init__(self, endpoint, auth, target=None, validation='ignore'): self.protocol = winrm.Protocol(endpoint=endpoint, transport='kerberos', server_cert_validation=validation, kerberos_delegation=True) self.target = target
def __init__(self, endpoint, username, keytab, num=1, target=None, *args, **kwargs): self.num = num for i in range(3): try: self.protocol = winrm.Protocol(endpoint=endpoint, transport='kerberos', kerberos_delegation=True, **kwargs) self.target = target self.logger = logging.getLogger('root') test_msg = """<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsmid="http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd"><s:Header/><s:Body><wsmid:Identify/></s:Body></s:Envelope>""" test_resp = self.protocol.send_message(test_msg) #print(test_resp) test_resp_xml = ET.fromstring(test_resp.decode('utf-8')) self.logger.debug( "[{anum}] Connected to WSMAN service at {host}, Vendor: {ven}, Version: {ver}" .format( anum=num, host=endpoint, ven=test_resp_xml.findtext( ".//{http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd}ProductVendor" ), ver=test_resp_xml.findtext( ".//{http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd}ProductVersion" ))) break except KerberosExchangeError as e: parsed_err = self.parse_krb5_err(str(e)) if (parsed_err == "Ticket expired" or (parsed_err.startswith("Credentials cache file ") and parsed_err.endswith(" not found"))): self.logger.warning( "[{anum}] No Kerberos ticket for {host}, requesting one ..." .format(anum=self.num, host=endpoint)) try: with open(keytab): pass gevent.subprocess.check_output( ["kinit", "-k", "-t", keytab, username], timeout=30, stderr=gevent.subprocess.STDOUT) self.logger.info( "[{anum}] Successfully retrieved Kerberos ticket for {host}, retrying command execution." .format(anum=self.num, host=endpoint)) except gevent.subprocess.CalledProcessError as e: self.logger.error( "[{anum}] Retrieving Kerberos ticket for {host} failed: {err}" .format(anum=self.num, host=endpoint, err=e.output.decode("utf-8"))) except gevent.subprocess.TimeoutExpired as e: self.logger.error( "[{anum}] Retrieving Kerberos ticket for {host} timed out!" .format(anum=self.num, host=endpoint)) except FileNotFoundError as e: self.logger.error( "[{anum}] Retrieving Kerberos ticket for {host} failed: {err}" .format(anum=self.num, host=endpoint, err=e)) except KeyError: self.logger.error( "[{anum}] Retrieving Kerberos ticket for {host} failed! Credentials missing!" .format(anum=self.num, host=endpoint)) continue elif parsed_err: self.logger.error( "[{anum}] An error occured during command execution on {node}: Kerberos: {err}" .format(anum=self.num, node=self.node, err=parsed_err)) self.statusmsg = parsed_err else: self.logger.error( "[{anum}] An error occured during command execution on {node}: Kerberos: {err}" .format(anum=self.num, node=self.node, err=str(e)))
def kerberos(action, host_ip, kdc, domain, host_name, powershell_script, password, username, port): action.logger.info('Running Kerberos connection') # Adds needed https and port number to host IP host_connection = 'https://{host_ip}:{port}/wsman'.format(host_ip=host_ip, port=port) action.logger.debug('PowerShell script: ' + powershell_script) udomain = domain.upper() # Config for krb5 file to the domain krb_config = '''[libdefaults] default_realm = {udomain} forwardable = true proxiable = true [realms] {udomain} = {{ kdc = {kdc} admin_server = {kdc} default_domain = {udomain} }} [domain_realm] .{domain} = {udomain} {domain} = {udomain}'''.format(udomain=udomain, domain=domain, kdc=kdc) action.logger.debug(krb_config) # Config for DNS dns = 'search %s\r\nnameserver %s' % (domain, kdc) action.logger.debug(dns) # Sends output from stdout on shell commands to logging. Preventing errors subprocess.call('mkdir -p /var/lib/samba/private', shell='true') subprocess.call('systemctl enable sssd', shell='true') # Setup realm to join the domain with open('/etc/krb5.conf', 'w') as f: f.write(krb_config) # Creates a Kerberos ticket kinit = '''echo '%s' | kinit %s@%s''' % (password, username, domain.upper()) response = subprocess.Popen(kinit, shell='true', stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = response.communicate() stdout = stdout.decode('utf-8') stderr = stderr.decode('utf-8') action.logger.info('Attempt to make Kerberos ticket stdout: ' + stdout) action.logger.info('Attempt to make Kerberos ticket stderr: ' + stderr) # DNS info so the plugin knows where to find the domain with open('/etc/resolv.conf', 'w') as f: f.write(dns) # Joins Komand to domain realm = '''echo '%s' | realm --install=/ join --user=%s %s''' % ( password, username, domain) response = subprocess.Popen(realm, shell='true', stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = response.communicate() stdout = stdout.decode('utf-8') stderr = stderr.decode('utf-8') action.logger.info('Attempt to join domain stdout: ' + stdout) action.logger.info('Attempt to join domain stderr: ' + stderr) # Allows resolution if A name not set for host with open('/etc/hosts', 'a') as f: f.write('\r\n' + host_ip + ' ' + host_name) # Runs the script on the host powershell_session = winrm.Session(host_connection, auth=(username, password), transport='kerberos') # Forces the protocol to not fail with self signed certs p = winrm.Protocol(endpoint=host_connection, transport='kerberos', username=username, password=password, server_cert_validation='ignore') powershell_session.protocol = p run_script = powershell_session.run_ps(powershell_script) exit_code = run_script.status_code error_value = run_script.std_err output = run_script.std_out try: error_value = error_value.decode('utf-8') except AttributeError: pass output = output.decode('utf-8') if exit_code != 0: action.logger.error(error_value) raise Exception( 'An error occurred in the PowerShell script, see logging for more info' ) return {'output': output, 'stderr': error_value}
def exec_command_win(cmd, hostname, user, password, skip_ret_code_check=False, connect_retry_count=3): """ Execute command on windows remote host :param cmd: :param hostname: :param user: :param password: :return: """ import winrm import requests for trc in range(connect_retry_count): try: p = winrm.Protocol(endpoint='http://' + hostname + ':5985/wsman', transport='plaintext', read_timeout_sec=360, operation_timeout_sec=300, username=user, password=password) shell_id = p.open_shell() break except (winrm.exceptions.WinRMOperationTimeoutError, winrm.exceptions.WinRMTransportError, requests.exceptions.ConnectionError, socket.error) as e: if trc == connect_retry_count: raise e sleep(CONNECT_RETRY_DELAY) if cmd is None: p.close_shell(shell_id) return print("Executing '%s' on %s..." % (cmd, hostname)) command_id = p.run_command(shell_id, cmd) stdout, stderr, retcode = p.get_command_output(shell_id, command_id) stdout = stdout.decode(ConsoleEncoding) stderr = stderr.decode(ConsoleEncoding) # These operations fail when the current user excluded from # the Administrators group, so just ignore the error. try: p.cleanup_command(shell_id, command_id) except winrm.exceptions.WinRMError: pass try: p.close_shell(shell_id) except winrm.exceptions.WinRMError: pass if skip_ret_code_check: return retcode, stdout, stderr else: if retcode != 0: print("Return code for command \'%s\' is %d.\n" % (cmd, retcode)) print("The command stdout:\n%s" % stdout) print("The command stderr:\n%s" % stderr) raise Exception('Command "%s" failed.' % cmd) else: return retcode, stdout, stderr