def exec(): client = Client("192.168.1.119", ssl=False, username="******", password="******") try: # cmd = "tasklist" # cmd = "taskkill /im MEGAsync.exe /f" cmd = "logoff 1" # cmd = 'powershell -Command {"{0:N2} MB" -f ((Get-ChildItem C:\\Users\\os\AppData\\Local\\Microsoft -Recurse | Measure-Object -Property Length -Sum -ErrorAction Stop).Sum / 1MB)}' # cmd = 'powershell -Command {Install-Module PSFolderSize}' # cmd = 'powershell -Command {Ps-FolderSize -Path "C:\\Users\\os\AppData\\Local\\Microsoft" }' # cmd = 'dir' # cmd = "taskkill /im bash.exe /f" stdout, stderr, rc = client.execute_cmd(cmd) except (WSManFaultError, ConnectionError, WinRMTransportError, AuthenticationError, ReadTimeout): print( "[!] ERROR WSManFaultError or ConnectionError or WinRMTransportError, AuthenticationError, ReadTimeout" ) return -1 # stdout, stderr, rc = client.execute_cmd("tasklist") print(stdout) print(stderr)
def plaintext_login(self, domain, username, password): try: from urllib3.connectionpool import log log.addFilter(SuppressFilter()) self.conn = Client(self.host, auth='ntlm', username=u'{}\\{}'.format(domain, username), password=password, ssl=False) # TO DO: right now we're just running the hostname command to make the winrm library auth to the server # we could just authenticate without running a command :) (probably) self.conn.execute_ps("hostname") self.admin_privs = True self.logger.success(u'{}\\{}:{} {}'.format(self.domain, username, password, highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else ''))) if not self.args.continue_on_success: return True except Exception as e: if "with ntlm" in str(e): self.logger.error(u'{}\\{}:{}'.format(self.domain, username, password)) else: self.logger.error(u'{}\\{}:{} "{}"'.format(self.domain, username, password, e)) return False
def _get_client(self, wsman): # the connection object was already created as part of test fixture # we need to apply it to the Client object and set the values so the # test will work with existing responses client = Client(None) client.wsman = wsman return client
def auth(self, domain=None, username=None, password=None, hash=None): if not username: raise AuthFailure('Username not specified') if not password and not hash: raise AuthFailure('Password or hash not specified') if not domain: domain = 'WORKGROUP' if hash != None and not ':' in hash: lmhash = '00000000000000000000000000000000:' hash = lmhash + hash try: if password: self.conn = Client(self.hostname, auth='ntlm', username=username, password=password, ssl=False, connection_timeout=self.timeout) else: self.conn = Client(self.hostname, auth='ntlm', username=username, password=hash, ssl=False, connection_timeout=self.timeout) # check if it works self.conn.execute_ps("hostname") return True except Exception as e: print('%s: %s' % (type(e), e)) return False
def WindowsConnect(DC, UN, PWD, COMMANDS): dc_client = Client(DC, username=UN, password=PWD, cert_validation=False, ssl=False) dc_date = dc_client.execute_cmd(COMMANDS) dc_date = dc_date[0].strip() return dc_date
def __init__(self, dns_svr, user, password, csv_dns_dm): self.dns_svr = dns_svr self.user = user self.password = password self.csv_dns_fw_dm = csv_dns_dm[0] self.csv_dns_rv_dm = csv_dns_dm[1] # WSman connection used to run powershell cmds on windows servers self.wsman_conn = WSMan(self.dns_svr, username=self.user, password=self.password, ssl=False) self.client_conn = Client(self.dns_svr, username=self.user, password=self.password, ssl=False)
def ExecCmd(dc, un, pwd, commands): dc_client = Client(dc, username=un, password=pwd, cert_validation=False, ssl=False) output = dc_client.execute_cmd(commands) output = output[0].strip() return output
def GetTime(dc): dc_client = Client(dc, username=svc_act_un, password=svc_act_pwd, cert_validation=False, ssl=False) dc_time = dc_client.execute_cmd('powershell.exe date') dc_time = dc_time[0].strip() return dc_time
def runpypsrp(fields): client = Client(fields[0].get(), username=fields[1].get(), password=fields[2].get()) temp = '' temp, streams, had_errors = client.execute_ps("GetWindowsArtifacts.ps1") f = open('temp', 'a+') f.write(temp) f.close() multiprompt(0)
class WinRMScan: def __init__(self, hostname, timeout): self.hostname = hostname self.timeout = timeout self.conn = None #TODO: use requests to check in http server for winrm is running def auth(self, domain=None, username=None, password=None, hash=None): if not username: raise AuthFailure('Username not specified') if not password and not hash: raise AuthFailure('Password or hash not specified') if not domain: domain = 'WORKGROUP' if hash != None and not ':' in hash: lmhash = '00000000000000000000000000000000:' hash = lmhash + hash try: if password: self.conn = Client(self.hostname, auth='ntlm', username=username, password=password, ssl=False, connection_timeout=self.timeout) else: self.conn = Client(self.hostname, auth='ntlm', username=username, password=hash, ssl=False, connection_timeout=self.timeout) # check if it works self.conn.execute_ps("hostname") return True except Exception as e: print('%s: %s' % (type(e), e)) return False def execute(self, command, get_output=False): try: r = self.conn.execute_cmd(command) except: r = self.conn.execute_ps(command) return r[0] def ps_execute(self, command, get_output=False): r = self.conn.execute_ps(command) return r[0] def disconnect(self): pass
def get_psr(config): errors = 0 results = [] try: ssl = config['protocol'].split('/')[1] except Exception as e: ssl = "" for member in config['members'].split(','): res = "" try: if ssl: client = Client(member, ssl=True, auth="ntlm", cert_validation=False, connection_timeout=3, username=config['user'], password=config['password']) else: client = Client(member, ssl=False, auth="ntlm", cert_validation=False, connection_timeout=3, username=config['user'], password=config['password']) stdout, stderr, _rc = client.execute_cmd(REMCMD) if "decode" in dir(stdout): res = stdout.decode() err = stderr.decode() else: res = stdout err = stderr if err: print("get_psr: {} -> err: {}".format(config, err), file=sys.stderr) errors += 1 except Exception as e: print("get_psr: Connect to {} failed: {}".format( member, e.args[0]), file=sys.stderr) errors += 1 results.append(res) return errors, config, results
def login(self): self.complete = False # Used to keep loop going if entered credentials are wrong while not self.complete: try: self.user = input("Enter your username: ") self.password = getpass() # Test credentials by running simple cmd on the DHCP server conn = Client(dhcp_svr, username=self.user, password=self.password, ssl=False) conn.execute_cmd('ipconfig') self.menu() # Runs next function (6) except Exception as e: # If login fails loops to begining displaying this error message print(e)
def hash_login(self, domain, username, ntlm_hash): try: from urllib3.connectionpool import log log.addFilter(SuppressFilter()) lmhash = '00000000000000000000000000000000:' nthash = '' #This checks to see if we didn't provide the LM Hash if ntlm_hash.find(':') != -1: lmhash, nthash = ntlm_hash.split(':') else: nthash = ntlm_hash ntlm_hash = lmhash + nthash self.hash = nthash if lmhash: self.lmhash = lmhash if nthash: self.nthash = nthash self.conn = Client(self.host, auth='ntlm', username=u'{}\\{}'.format(domain, username), password=ntlm_hash, ssl=False) # TO DO: right now we're just running the hostname command to make the winrm library auth to the server # we could just authenticate without running a command :) (probably) self.conn.execute_ps("hostname") self.admin_privs = True self.logger.success(u'{}\\{}:{} {}'.format(self.domain, username, self.hash, highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else ''))) if not self.args.continue_on_success: return True except Exception as e: if "with ntlm" in str(e): self.logger.error(u'{}\\{}:{}'.format(self.domain, username, self.hash)) else: self.logger.error(u'{}\\{}:{} "{}"'.format(self.domain, username, self.hash, e)) return False
def test_sanitise_clixml_with_no_errors(self): clixml_path = os.path.join(os.path.dirname(__file__), "data", "test_sanitise_clixml_with_no_errors.xml") with open(clixml_path, "r") as fd: clixml = fd.read() expected = "" actual = Client.sanitise_clixml(clixml) assert actual == expected
def test_winrm() -> typing.Tuple[str, str, int]: server = os.environ["PYPSRP_SERVER"] username = os.environ["PYPSRP_USERNAME"] password = os.environ["PYPSRP_PASSWORD"] with Client(server, username=username, password=password, cert_validation=False) as c: return c.execute_cmd("whoami.exe")
def fetch(ctx, remote, local, instance): """ Fetch remote file from instance. """ cloud_name = ctx.obj['cloud_name'] LOGGER.debug('cloud_name:%s remote:%s local:%s instance:%s', cloud_name, remote, local, instance) if cloud_name: # Note: All winrm ops are supported. utils.cloud_run(cloud_name, ['winrm']) return inst = MechInstance(instance) if inst.created: utils.suppress_urllib3_errors() client = Client(inst.get_ip(), username=inst.user, password=inst.password, ssl=False) client.fetch(remote, local) click.echo("Fetched")
def test_sanitise_clixml_with_error(self): clixml_path = os.path.join(os.path.dirname(__file__), 'data', 'test_sanitise_clixml_with_error.xml') with open(clixml_path, 'r') as fd: clixml = fd.read() expected = "fake : The term 'fake' is not recognized as the name of a cmdlet, function, script file, or operable program. Check \r\n" \ "the spelling of the name, or if a path was included, verify that the path is correct and try again.\r\n" \ "At line:1 char:1\r\n" \ "+ fake cmdlet\r\n" \ "+ ~~~~\r\n" \ " + CategoryInfo : ObjectNotFound: (fake:String) [], CommandNotFoundException\r\n" \ " + FullyQualifiedErrorId : CommandNotFoundException\r\n" \ " \r\n" actual = Client.sanitise_clixml(clixml) assert actual == expected
def connect(host: str): global CONNECTIONS if not test(host): return False _host = CFG_HOSTS[host] c = Client( server = _host.get("server", None), port = _host.get("port", 5985), path = _host.get("path", "wsman"), username = _host.get("username" , r''), password = _host.get("password" , r''), auth = _host.get("auth", "ntlm"), ssl = _host.get("ssl", False), ) CONNECTIONS.append((host, c)) return True
help='Remote computer to run against, usually a DC') par.add_argument('--user', type=str, help='Username') par.add_argument('--password', type=str, help='Password') par.add_argument('--ask-pass', help='Ask for password', action='store_true') par.add_argument('--remove', help='Remove the record', action='store_true') args = par.parse_args() print(args) if args.ask_pass: password = getpass.getpass("Enter password: "******"Specify password if ask-pass not setup") exit(-1) password = args.password ms = Client(args.computer, username=args.user, password=password, ssl=False) if args.remove: #Remove-DnsServerResourceRecord -ZoneName "contoso.com" -RRType "A" -Name "Host01" -RecordData "10.17.1.41" ps_cmd = "Remove-DnsServerResourceRecord -name '%s' -ZoneName '%s' -RecordData '%s' -RRType 'A' -force" % ( args.name, args.zone, args.ip) else: ps_cmd = "Add-dnsserverresourcerecorda -name '%s' -ZoneName '%s' -IPV4Address '%s' -AllowUpdateAny" % ( args.name, args.zone, args.ip) output, streams, had_errors = ms.execute_ps(ps_cmd) print("Status: %s, Success: %s" % (output, not had_errors)) f = open("./test", "a") f.write("Testing!!") f.close()
class Server: # Initiation de l'objet def __init__(self, **attributes): for attr_name, attr_value in attributes.items(): setattr(self, attr_name.strip(), str(attr_value).strip()) # Afficher l'objet avec la fonction dir # Retourne un objet json def __repr__(self): return json.dumps(self.__dict__) # Afficher l'objet avec la fonction print # Retourne un objet json def __str__(self): return json.dumps(self.__dict__) # Transforme une chaîne de caractères en une liste # Retourne une liste def __strToList(self, data): data = data.split("\n") listData = [] for i in range(len(data)): if i > 2 and data[i].strip() != '': listData.append(data[i].strip()) return listData # Créer une connexion entre la machine Linux et un serveur Windows Server en utilisant le module pypsrp def creatServer(self): self.client = None try: self.client = Client(self.name, username=self.username, password=self.password, ssl=False) except: print("Problème de connexion au server [ %s ] !!" % self.name) # Retourne une liste contenant les DistinguishedName existants dans un serveur Windows Server def getAllPaths(self): paths =[] err = False script = "Get-ADOrganizationalUnit -Filter 'Name -notlike \"Domain Controllers\"' | Format-Table DistinguishedName -A" try: output, streams, had_errors = self.client.execute_ps(script) if had_errors: print("For", path, "\n".join([str(s) for s in streams.error])) elif len(output) > 0: paths = self.__strToList(output) except: err = True print("Problème de connexion au moment de la consultation des comptes utilisateurs !!") return err, paths # Retourne une liste contenant l'ensemble des utilisateurs existants dans une machine Windows Server def getAllUsers(self): listUsers =[] err = False errpath, paths = self.getAllPaths() if errpath: err = True return err, listUsers for path in paths: script = "Get-ADUser -Filter * -SearchBase '%s' | Format-Table DistinguishedName -A" % path try: output, streams, had_errors = self.client.execute_ps(script) if had_errors: print("For", path, "\n".join([str(s) for s in streams.error])) elif len(output) > 0: listUsers = self.__strToList(output) except: err = True print("Problème de connexion au moment de la consultation des comptes utilisateurs !!") break return err, listUsers
from pypsrp.client import Client if True: # set json variables with open('f5_backup.json') as f: js = json.load(f) backup_server_un = js['SERVER_UN'] backup_server_pwd = js['SERVER_PWD'] hosts_pwd = js['HOSTS_PWD'] if True: # set local variables date_format = time.strftime("%Y%m%d") backup_server_ip = '+IP OF BACKUP SERVER HERE+' backup_server_domain = '+DOMAIN OF BACKUP SERVER HERE+' backup_drive = '+DRIVE WHERE BACKUPS ARE STORED ON SERVER HERE+' if True: # set pypsrp client connection settings to CA backup_server_client = Client( backup_server_ip, username=f"{backup_server_domain}\\{backup_server_un}", password=backup_server_pwd, cert_validation=False, ssl=False) if True: # define device connect function def Connect(dev, addr, un, pwd): client = paramiko.SSHClient() client.load_system_host_keys() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(addr, port=22, username=un, password=pwd, look_for_keys=False, timeout=10) channel = client.invoke_shell()
class Dns(): def __init__(self, dns_svr, user, password, csv_dns_dm): self.dns_svr = dns_svr self.user = user self.password = password self.csv_dns_fw_dm = csv_dns_dm[0] self.csv_dns_rv_dm = csv_dns_dm[1] # WSman connection used to run powershell cmds on windows servers self.wsman_conn = WSMan(self.dns_svr, username=self.user, password=self.password, ssl=False) self.client_conn = Client(self.dns_svr, username=self.user, password=self.password, ssl=False) ###################################### FAILFAST ###################################### # Check if zones exist on DNS server def failfast(self): all_zones, bad_zones = ([] for i in range(2)) # Create combined list of all forward and reverse zones for csv_dict in self.csv_dns_fw_dm: for zone in csv_dict.keys(): all_zones.append(zone) for csv_dict in self.csv_dns_rv_dm: for zone in csv_dict.keys(): all_zones.append(zone) # Interate through all zones and see if exist on DNS server for zone in all_zones: with RunspacePool(self.wsman_conn) as pool: print('-', zone) ps = PowerShell(pool) # The powershell cmd is "Get-DhcpServerv4Reservation -scopeid 192.168.200.0" ps.add_cmdlet("Invoke-Expression").add_parameter("Command", "Get-DnsServerZone {}".format(zone)) ps.add_cmdlet("Out-String").add_parameter("Stream") ps.invoke() dns_zones = ps.output if len(dns_zones) == 0: bad_zones.append(zone) # If any of the scopes dont not exist values are returned to main.py (which also casues script to exit) if len(bad_zones) != 0: return '!!! Error - The following zones dont exist on the DNS server: \n{}'.format(bad_zones) ###################################### Get DNS reservations ###################################### def get_entries(self): dns_fw_dm, dns_rv_dm = ([] for i in range(2)) # On a per-zone basis gets all the current DNS entries that will then be compared to those in the CSV for csv_dns_fw in self.csv_dns_fw_dm : for domain in csv_dns_fw.keys(): with RunspacePool(self.wsman_conn) as pool: ps = PowerShell(pool) # The powershell cmd is "Get-DnsServerResourceRecord -ZoneName stesworld.com -RRType A" ps.add_cmdlet("Invoke-Expression").add_parameter("Command", "Get-DnsServerResourceRecord -ZoneName {} -RRType A".format(domain)) ps.add_cmdlet("Out-String").add_parameter("Stream") ps.invoke() dns_fw_records = ps.output # From the ps output create a list for the dns_fw DM dict value [('ip', 'name', ttl)] ip_name_ttl = [] if len(dns_fw_records) == 0: # skips if no A records in the zone pass else: for a in dns_fw_records[3:-2]: # Elimates headers and trailing blank lines a = a.split() ip_name_ttl .append((a[-1], a[0].lower(), a[-2])) # Add the list as the value for for a dict where the zone name is the key [{fw_zone: [(ip, name, ttl)]}] dns_fw_dm.append({domain: ip_name_ttl}) # On a per-reverse-zone basis gets all the current DNS entries that will then be compared to those in the CSV for csv_dns_rv in self.csv_dns_rv_dm: for rev_zone in csv_dns_rv.keys(): with RunspacePool(self.wsman_conn) as pool: ps = PowerShell(pool) ps.add_cmdlet("Invoke-Expression").add_parameter("Command", "Get-DnsServerResourceRecord -ZoneName {} -RRType PTR".format(rev_zone)) ps.add_cmdlet("Out-String").add_parameter("Stream") ps.invoke() dns_rv_records = ps.output hst_name = [] if len(dns_rv_records) == 0: # skips if no PTR records in the zone pass else: for ptr in dns_rv_records[3:-2]: ptr = ptr.split() hst_name.append((ptr[0], ptr[-1].lower())) dns_rv_dm.append({rev_zone: hst_name}) # creates DM where rv_zone name is the key [{rv_zone: [(host, domain_name)]}] return [dns_fw_dm, dns_rv_dm] ###################################### Compare new Vs current resv ###################################### def verify_csv_vs_svr(self, dns_dm): dns_fw_dm = dns_dm[0] dns_rv_dm = dns_dm[1] csv_name, csv_rv_name, dns_fw_name, dns_rv_name, used_fw_fqdn, used_rv_fqdn = ([] for i in range(6)) # Create a list tuples of all FQDNs from CSV DMs (zone, fqdn) for dict_domain in self.csv_dns_fw_dm: domain = '.' + list(dict_domain.keys())[0] for all_values in dict_domain.values(): for each_value in all_values: csv_name.append((list(dict_domain.keys())[0], each_value[1] + domain)) for dict_domain in self.csv_dns_rv_dm: for all_values in dict_domain.values(): for each_value in all_values: csv_rv_name.append((list(dict_domain.keys())[0], each_value[1])) # Create a list tuples of all FQDNs from DNS DMs (zone, fqdn) for dict_domain in dns_fw_dm: domain = '.' + list(dict_domain.keys())[0] for all_values in dict_domain.values(): for each_value in all_values: dns_fw_name.append((list(dict_domain.keys())[0], each_value[1] + domain)) for dict_domain in dns_rv_dm: for all_values in dict_domain.values(): for each_value in all_values: dns_rv_name.append((list(dict_domain.keys())[0], each_value[1])) # Create list of any already used FQDNs in DNS by removing any unique values used_fw_fqdn = set(csv_name) & set(dns_fw_name) used_rv_fqdn = set(csv_rv_name) & set(dns_rv_name) used_fqdn = sorted(list(used_fw_fqdn)) + sorted(list(used_rv_fqdn)) # Compares FQDNs in CSV to FQDNs on DNS server, will list any in the CSV that are missing from DNS server missing_fw_fqdn = set(csv_name) - set(dns_fw_name) missing_rv_fqdn = set(csv_rv_name) - set(dns_rv_name) missing_fqdn = sorted(list(missing_fw_fqdn)) + sorted(list(missing_rv_fqdn)) # What is returned to main.py to kill script if any duplicates. len(csv_name) is used to compare pre and post number of entries len_csv = str(len(dns_fw_name)) + '/' + str(len(dns_rv_name)) # Number of added records in the format A/PTR output = {'len_csv': len_csv, 'used_entries': used_fqdn, 'missing_entries': missing_fqdn} return output ###################################### Creates new CSV with no scope prefix ###################################### def create_new_csv(self, type, csv_file, temp_csv): self.num_new_entries = 0 # Creates a temp csv file with header and format compatible with DNS server import. if type == 'add': with open(temp_csv, 'w') as x: writer = csv.writer(x) writer.writerow(['ZoneName','Name','IPAddress','TimeToLive']) for dict_domain in self.csv_dns_fw_dm: domain = list(dict_domain.keys())[0] for all_values in dict_domain.values(): for each_value in all_values: self.num_new_entries += 1 # Number of reservatiosn to be added writer.writerow([domain,each_value[1],each_value[0],each_value[2]]) # Dont add header on these as windows ps cmd wont understand 'ZoneName', luckily can do on position number so no need for header. elif type == 'remove': self.temp_csv1 = temp_csv.replace(".csv", "1.csv") # Extra temp file required for removing DNS RV entries with open(temp_csv, 'w') as x: writer = csv.writer(x) writer.writerow(['ZoneName','Name', 'RRType']) for dict_domain in self.csv_dns_fw_dm: domain = list(dict_domain.keys())[0] for all_values in dict_domain.values(): for each_value in all_values: self.num_new_entries += 1 # Number of reservatiosn to be added writer.writerow([domain,each_value[1],'A']) with open(self.temp_csv1, 'w') as x: writer = csv.writer(x) writer.writerow(['ZoneName','Name', 'RRType']) for dict_domain in self.csv_dns_rv_dm: domain = list(dict_domain.keys())[0] for all_values in dict_domain.values(): for each_value in all_values: writer.writerow([domain,each_value[0],'PTR']) # Used only with pytest to test new CSV file created and the contents are correct pytest_csv = [] with open(temp_csv, 'r') as x: csv_read = csv.reader(x) for row in csv_read: pytest_csv.append(row) if type == 'remove': # To test both CSVs if remove pytest_csv1 = [] with open(self.temp_csv1, 'r') as x: csv_read = csv.reader(x) for row in csv_read: pytest_csv1.append(row) return [pytest_csv, pytest_csv1] else: return pytest_csv ###################################### Adds or Removes the DHCP reservations ###################################### def deploy_csv(self, type, temp_csv, win_dir): win_dir1 = win_dir.replace(".csv", "1.csv") # Extra temp file required for removing DNS RV entries self.num_new_entries = str(self.num_new_entries) + '/' + str(self.num_new_entries) # To make it A/PTR records, should be same as deployed in the 1 cmd # Copy the new CSV File onto DHCP server, script will fail if it cant try: self.client_conn.copy(temp_csv, win_dir) if type == 'remove': self.client_conn.copy(self.temp_csv1, win_dir1) except Exception as e: # If copy fails script fails print("!!! Error - Could not copy CSV file to DNS server, investigate the below error before re-running the script.\n{}".format(e)) exit() # Add DNS entries if type == 'add': with RunspacePool(self.wsman_conn) as pool: ps = PowerShell(pool) ps.add_cmdlet("Import-Csv").add_argument("{}".format(win_dir)).add_cmdlet("Add-DNSServerResourceRecordA").add_parameter("-CreatePtr") ps.invoke() output = [self.num_new_entries, [ps.had_errors], [ps.streams.error]] # Remove DNS entries, have to spilt into multiple cmds due to bug with "Remove-DNSServerResourceRecord" where cant use RRtype from CSV elif type == 'remove': with RunspacePool(self.wsman_conn) as pool: ps = PowerShell(pool) ps.add_cmdlet("Import-Csv").add_argument("{}".format(win_dir)).add_cmdlet("Remove-DNSServerResourceRecord").add_parameter("RRtype", "A").add_parameter("-Force") ps.invoke() output = [self.num_new_entries, [ps.had_errors], [ps.streams.error]] # adds the errors as lists so can add outputs from next cmd with RunspacePool(self.wsman_conn) as pool: ps = PowerShell(pool) ps.add_cmdlet("Import-Csv").add_argument("{}".format(win_dir1)).add_cmdlet("Remove-DNSServerResourceRecord").add_parameter("RRtype", "PTR").add_parameter("-Force") ps.invoke() output[1].append(ps.had_errors) output[2].append(ps.streams.error) # Cleanup temp files try: os.remove(temp_csv) self.client_conn.execute_cmd("del {}".format(win_dir.replace("/", "\\"))) # Windows wont take / format with the cmd if type == 'remove': os.remove(self.temp_csv1) self.client_conn.execute_cmd("del {}".format(win_dir1.replace("/", "\\"))) # Windows wont take / format with the cmd except Exception as e: # If delete fails warns user print("!!! Warning - Could not delete temporary files off DNS server, you will have to do manually.\n{}".format(e)) return output
class winrm(connection): def __init__(self, args, db, host): self.domain = None self.server_os = None connection.__init__(self, args, db, host) @staticmethod def proto_args(parser, std_parser, module_parser): winrm_parser = parser.add_parser('winrm', help="own stuff using WINRM", parents=[std_parser, module_parser]) winrm_parser.add_argument("-H", '--hash', metavar="HASH", dest='hash', nargs='+', default=[], help='NTLM hash(es) or file(s) containing NTLM hashes') winrm_parser.add_argument("--no-bruteforce", action='store_true', help='No spray when using file for username and password (user1 => password1, user2 => password2') winrm_parser.add_argument("--continue-on-success", action='store_true', help="continues authentication attempts even after successes") winrm_parser.add_argument("--port", type=int, default=0, help="Custom WinRM port") dgroup = winrm_parser.add_mutually_exclusive_group() dgroup.add_argument("-d", metavar="DOMAIN", dest='domain', type=str, default=None, help="domain to authenticate to") dgroup.add_argument("--local-auth", action='store_true', help='authenticate locally to each target') cgroup = winrm_parser.add_argument_group("Command Execution", "Options for executing commands") cgroup.add_argument('--no-output', action='store_true', help='do not retrieve command output') cgroup.add_argument("-x", metavar="COMMAND", dest='execute', help="execute the specified command") cgroup.add_argument("-X", metavar="PS_COMMAND", dest='ps_execute', help='execute the specified PowerShell command') return parser def proto_flow(self): self.proto_logger() if self.create_conn_obj(): self.enum_host_info() self.print_host_info() if self.login(): if hasattr(self.args, 'module') and self.args.module: self.call_modules() else: self.call_cmd_args() def proto_logger(self): self.logger = CMEAdapter(extra={'protocol': 'WINRM', 'host': self.host, 'port': 'NONE', 'hostname': 'NONE'}) def enum_host_info(self): # smb no open, specify the domain if self.args.domain: self.domain = self.args.domain self.logger.extra['hostname'] = self.hostname else: try: smb_conn = SMBConnection(self.host, self.host, None) try: smb_conn.login('', '') except SessionError as e: if "STATUS_ACCESS_DENIED" in e.message: pass self.domain = smb_conn.getServerDNSDomainName() self.hostname = smb_conn.getServerName() self.server_os = smb_conn.getServerOS() self.logger.extra['hostname'] = self.hostname try: smb_conn.logoff() except: pass except Exception as e: logging.debug("Error retrieving host domain: {} specify one manually with the '-d' flag".format(e)) if self.args.domain: self.domain = self.args.domain if self.args.local_auth: self.domain = self.hostname def print_host_info(self): if self.args.domain: self.logger.info(self.endpoint) else: self.logger.info(u"{} (name:{}) (domain:{})".format(self.server_os, self.hostname, self.domain)) self.logger.info(self.endpoint) def create_conn_obj(self): endpoints = [ 'https://{}:{}/wsman'.format(self.host, self.args.port if self.args.port else 5986), 'http://{}:{}/wsman'.format(self.host, self.args.port if self.args.port else 5985) ] for url in endpoints: try: requests.get(url, verify=False, timeout=3) self.endpoint = url if self.endpoint.startswith('https://'): self.port = self.args.port if self.args.port else 5986 else: self.port = self.args.port if self.args.port else 5985 self.logger.extra['port'] = self.port return True except Exception as e: if 'Max retries exceeded with url' not in str(e): logging.debug('Error in WinRM create_conn_obj:' + str(e)) return False def plaintext_login(self, domain, username, password): try: from urllib3.connectionpool import log log.addFilter(SuppressFilter()) self.conn = Client(self.host, auth='ntlm', username=u'{}\\{}'.format(domain, username), password=password, ssl=False) # TO DO: right now we're just running the hostname command to make the winrm library auth to the server # we could just authenticate without running a command :) (probably) self.conn.execute_ps("hostname") self.admin_privs = True self.logger.success(u'{}\\{}:{} {}'.format(self.domain, username, password, highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else ''))) if not self.args.continue_on_success: return True except Exception as e: if "with ntlm" in str(e): self.logger.error(u'{}\\{}:{}'.format(self.domain, username, password)) else: self.logger.error(u'{}\\{}:{} "{}"'.format(self.domain, username, password, e)) return False def hash_login(self, domain, username, ntlm_hash): try: from urllib3.connectionpool import log log.addFilter(SuppressFilter()) lmhash = '00000000000000000000000000000000:' nthash = '' #This checks to see if we didn't provide the LM Hash if ntlm_hash.find(':') != -1: lmhash, nthash = ntlm_hash.split(':') else: nthash = ntlm_hash ntlm_hash = lmhash + nthash self.hash = nthash if lmhash: self.lmhash = lmhash if nthash: self.nthash = nthash self.conn = Client(self.host, auth='ntlm', username=u'{}\\{}'.format(domain, username), password=ntlm_hash, ssl=False) # TO DO: right now we're just running the hostname command to make the winrm library auth to the server # we could just authenticate without running a command :) (probably) self.conn.execute_ps("hostname") self.admin_privs = True self.logger.success(u'{}\\{}:{} {}'.format(self.domain, username, self.hash, highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else ''))) if not self.args.continue_on_success: return True except Exception as e: if "with ntlm" in str(e): self.logger.error(u'{}\\{}:{}'.format(self.domain, username, self.hash)) else: self.logger.error(u'{}\\{}:{} "{}"'.format(self.domain, username, self.hash, e)) return False def execute(self, payload=None, get_output=False): try: r = self.conn.execute_cmd(self.args.execute) except: self.logger.debug('Cannot execute cmd command, probably because user is not local admin, but powershell command should be ok !') r = self.conn.execute_ps(self.args.execute) self.logger.success('Executed command') self.logger.highlight(r[0]) def ps_execute(self, payload=None, get_output=False): r = self.conn.execute_ps(self.args.ps_execute) self.logger.success('Executed command') self.logger.highlight(r[0])
def run(): log_write('Sync vpn users...') # Проверка существования файла VPNUsersList try: userslist = open(get_config('VPNUsersList'), 'r').read().split() except IOError as err: open(get_config('VPNUsersList'), 'w') userslist = [] # # Подключение к серверу Active Directory client = Client(get_config('ADServer') + "." + get_config('DomainRealm'), auth="kerberos", ssl=False, username=get_config('ADUserName'), password=get_config('ADUserPassword')) # Получение списка пользователей и их паролей для тех, у кого поле wwwhomepage начинается с VPNMask script = """([adsisearcher]"(objectcategory=user)").FindAll() | where {$_.properties['wwwhomepage'] -like '""" + get_config( 'VPNMask' ) + """*'} | %{ $_.GetDirectoryEntry() } | ForEach-Object {$_.samaccountname, $_.wwwhomepage}""" try: adusers, streams, had_error = client.execute_ps(script) except: log_write('[adsisearcher] objectcategory=user powershell error') adusers = adusers.splitlines() # # Добавление и обновление пользователей pos = 0 while pos < len(adusers): # Получение исходного пароля пользователя password = adusers[pos + 1][len(get_config('VPNMask')):] if len(password) > 5: # Проверка длины пароля # Генерирование соли и пароля пользователя sha_salt = os.urandom(10) password = sha_salt.hex() + hashlib.pbkdf2_hmac( hash_name='sha256', password=password.encode(), salt=sha_salt, iterations=100).hex() try: userpos = userslist.index(adusers[pos]) userslist[userpos + 1] = password log_write('Updated user ' + adusers[pos]) except ValueError: userslist.append(adusers[pos]) userslist.append(password) log_write('Added user ' + adusers[pos]) else: # Удаление пользователя и его пароля (не соответствие длины пароля) adusers.pop(pos) adusers.pop(pos) pos = pos + 2 # # Удаление из списка userslist, пользователей более не присутствующих в adusers for user in userslist[::2]: try: adusers.index(user) except ValueError: pos = userslist.index(user) # Удаление пользователя и его пароля userslist.pop(pos) userslist.pop(pos) log_write('Deleted user ' + user) # # Запись в файл VPNUsersList with open(get_config('VPNUsersList'), 'w') as result: pos = 0 while pos < len(userslist): result.write(userslist[pos] + ' ' + userslist[pos + 1] + '\n') pos += 2
def sync_from_ms_dhcp_server(time_tag, ipam_token, ipam_addresses_url, log_file, EMAIL_CONTENT_FILE, webex_teams_api): """Connect to DHCP server via PowerShell Remoting, import its dhcp scopes leases, then process them in IPAM using the passed ipam token, url and timestamp arguments. """ client = Client(DHCP_SERVER_FQDN, username=DHCP_SERVER_USERNAME, password=DHCP_SERVER_PASSWORD, ssl=DHCP_SERVER_SSL) # validate that all entered DHCP scopes in the list env variable are valid IP subnet addresses. # If any invalid entry is found, exit the program. for scope in DHCP_SERVER_SCOPES: if not is_valid_ipv4_address(scope): print("At least one invalid scope is found in MS DHCP Server scopes list. " \ "Please use valid IP subnet DHCP scope entries and retry.") sys.exit(1) # All scopes are valid, proceed with the sync from the DHCP server: for scope in DHCP_SERVER_SCOPES: command = r"Get-DhcpServerv4Lease -Scopeid %s" % scope try: dhcp_server_output, streams, had_errors = client.execute_ps( command) except (requests.exceptions.Timeout, requests.exceptions.ConnectionError, pypsrp.exceptions.AuthenticationError, requests.exceptions.HTTPError) as error: print_with_timestamp_and_log("Unable to connect to the DHCP Server. Please verify " \ "settings and reachability.", log_file) cleanup_before_exit(log_file, email_body, EMAIL_CONTENT_FILE) sys.exit(1) formatted_dhcp_server_output = dhcp_server_output.split("\n") print( "\nSyncing the leased hosts from the MS DHCP Server, scope %s..." % scope) log_file.write( "\nSyncing the leased hosts from the MS DHCP Server, scope %s...\n" % scope) # Iterate through the list of hosts leases for this scope, starting from index 3 # to skip the empty line, then column names line, then the delimiter line: for lease in range(3, len(formatted_dhcp_server_output) - 2): lease_list = formatted_dhcp_server_output[lease].split() payload = "" # when length of lease_list is 8, this means all the fields are populated # including the hostname if (len(lease_list) == 8) & (lease_list[4] == "Active"): payload = { "subnetId": str(PHPIPAM_SUBNET_ID), "ip": lease_list[0], "is_gateway": "0", "description": lease_list[3], "hostname": lease_list[3], "mac": lease_list[2], "owner": TAG_MSDHCP, "note": str(time_tag) } # when length of lease_list is 7, this means the hostname field is empty. # MAC address field is shifted to the left after the string split. elif (len(lease_list) == 7) & (lease_list[3] == "Active"): payload = { "subnetId": str(PHPIPAM_SUBNET_ID), "ip": lease_list[0], "is_gateway": "0", "description": "N/A", "hostname": "N/A", "mac": lease_list[2], "owner": TAG_MSDHCP, "note": str(time_tag) } # Add the host to the IPAM if it's an active lease: if payload != "": process_host_in_ipam(lease_list[0], ipam_token, ipam_addresses_url, payload, log_file, email_body, EMAIL_CONTENT_FILE, webex_teams_api)
import pypsrp from pypsrp.client import Client if True: # set global variables now = datetime.datetime.now() month = '{:02d}'.format(now.month) day = '{:02d}'.format(now.day) device_hostname = '''+DEVICE HOSTNAME HERE+''' user = r'''+MS CA USERNAME WITH DOMAIN HERE+''' pwd = '''+MS CA PASSWORD HERE+''' ca = '''+MS CA IP OR RESOLVABLE HOSTNAME HERE+''' date_format = f'{now.year}{month}{day}' csrname = f'{device_hostname}_{now.year}{month}{day}.txt' ca_drive = r'''+PATH TO DRIVE WHERE CERTIFICATES ARE MANAGED ON MS CA HERE+''' submit_command = 'certreq.exe -submit -config -' certname = f'{now.year}{month}{day}.cer' if True: # set pypsrp client connection settings to CA ca_client = Client(f"{ca}", username=f"{user}", password=pwd, cert_validation=False, ssl=False) if True: # copy csr to CA with pypsrp client # !!!applicable csr must be present in directory where this is run!!! ca_client.copy(csrname, f"{ca_drive}\\{csrname}") if True: # 'submit'/sign csr on CA with pypsrp client ca_client.execute_cmd( f'{submit_command} {ca_drive}\\{csrname} {ca_drive}\\{certname}') if True: # fetch cert from CA # !!!will put certificate in directory where this is run!!! ca_client.fetch(f"{ca_drive}\\{certname}", certname)
call = connect_ssh(f'cat /config/httpd/conf/ssl.csr/{csrname}', True) for idx, val in enumerate(call): if 'BEGIN' in val: csr_start_index = idx csr_split = call[csr_start_index:] if True: # write csr variable to local csr file print("Writing CSR to local file...") with open(f'{csrname}', 'w+') as csr: for l in csr_split: csr.write(l) if True: # set pypsrp client connection settings to CA ca_client = Client(ca_ip, username=f"{ca_domain}\\{ca_un}", password=ca_pwd, cert_validation=False, ssl=False) if True: # copy local csr file to CA with pypsrp client print("Copying local CSR file to CA...") ca_client.copy(csrname, f"{cert_drive}\\{csrname}") if True: # 'submit'/sign csr on CA with pypsrp client print("Signing CSR on CA...") ca_client.execute_cmd( f'certreq.exe -submit -config - {cert_drive}\\{csrname} {cert_drive}\\{certname}' ) if True: # fetch cert file from CA and store as new name locally print("Fetching new signed certificate from CA...") new_certname = f'{cn_short}_{date_format}.crt' ca_client.fetch(f"{cert_drive}\\{certname}", new_certname) if True: # read cert file to variable
#!/usr/bin/env python import sys from pypsrp.client import Client def arg_check(): if len(sys.argv) < 2: print('Warning: Need to provide ip for windows instance.') sys.exit(1) if __name__ == '__main__': arg_check() server = sys.argv[1] ps = sys.argv[2] client = Client(server, username="******", password="******", ssl=False) # execute some powershell stdout, stderr, rc = client.execute_ps(ps) print("stdout:{}".format(stdout)) print("stderr:{}".format(stderr)) print("rc:{}".format(rc))
if True: # Set environment variables with open('create-pys_f5.json') as f: js = json.load(f) backup_server_un = js['BS_UN'] backup_server_pwd = js['BS_PWD'] if True: # Set local variables backup_server_ip = '+BACKUP SERVER IP HERE+' backup_server_domain = '+BACKUP SERVER DOMAIN HERE+' backup_drive = '+DRIVE WHERE BACK-UPS ARE SAVED+' device_files = [] local_dev_files = [] device = [] if True: # Set pypsrp client backup_server_client = Client( backup_server_ip, username=f"{backup_server_domain}\\{backup_server_un}", password=backup_server_pwd, cert_validation=False, ssl=False) if True: # Create file directories command = subprocess.Popen('mkdir config_files', stdout=subprocess.PIPE, shell=True) run = command.communicate() command = subprocess.Popen('mkdir py_files', stdout=subprocess.PIPE, shell=True) run = command.communicate() if True: # Get list of backup files from backup server file_out = backup_server_client.execute_cmd(f'dir "{backup_drive}"') filelist = file_out[0] filelist = filelist.strip()
def test_sanitise_clixml_not_clixml(self): clixml = "stderr line" expected = clixml actual = Client.sanitise_clixml(clixml) assert actual == expected