Sitemap

HTB: Fluffy

9 min readSep 24, 2026

--

This machine is built on Active Directory and shows how a set of seemingly limited privileges can be chained to compromise a domain.

Introduction

I’ll keep the initial enumeration and straightforward steps brief, and focus this write-up on the parts I found most interesting and the new techniques I learned, especially the BloodHound ACL attack path, Shadow Credentials, and AD CS / ESC16 exploitation.

The main attack path was:

j.fleischman
│
▼
SMB / IT
│
▼
NTLM Hash Leak
│
▼
p.agila
│
▼
Service Account Managers
│
│ GenericAll
▼
Service Accounts
│
├──────── GenericWrite ────────► winrm_svc
│ │
│ ▼
│ WinRM
│ │
│ ▼
│ user.txt
│
└──────── GenericWrite ────────► ca_svc
│
▼
ESC16
│
▼
Administrator
│
▼
root.txt

Initial Enumeration

The target was an Active Directory Domain Controller for:

Domain: fluffy.htb
DC: dc01.fluffy.htb
IP: 10.129.232.88

I started with the usual service enumeration and SMB discovery.

Press enter or click to view image in full size

Since SMB was accessible, I enumerated the available shares and found an interesting share IT

Press enter or click to view image in full size

The share contained a PDF that provided information about a vulnerability relevant to the environment.

The interesting part was that this vulnerability could be abused to trigger an NTLM authentication attempt, allowing an NTLM hash to be captured.

This eventually gave me credentials for: p.agila

At this point, I moved from basic enumeration to Active Directory enumeration.

Active Directory Enumeration

With valid domain credentials, I used BloodHound to map users, groups, and ACL relationships

bloodhound-python -d fluffy.htb  -u 'p.agila' -p '[redacted]' -ns 10.129.232.88 -c all

Once I had Neo4j and BloodHound installed, I imported my collected data and started to analyze the Active Directory graph to find interesting relationships and potential attack paths.

The interesting part wasn’t a single vulnerable account, but the way several permissions could be chained together.

Press enter or click to view image in full size

The first relevant relationship was:

p.agila
│
│ MemberOf
▼
Service Account Managers
│
│ GenericAll
▼
Service Accounts

This immediately gave me an interesting direction to investigate.

BloodHound ACL Chain

Press enter or click to view image in full size

GenericAll

BloodHound showed that:

Service Account Managers
│
│ GenericAll
▼
Service Accounts

Since p.agila was a member of Service Account Managers, this meant that p.agila could exercise the control inherited from that group over Service Accounts.

The important point here was that the target of the GenericAll permission was a group, not an individual user.

That made the group membership itself part of the attack path.

GenericWrite over winrm_svc

BloodHound also showed:

Service Accounts
│
│ GenericWrite
▼
winrm_svc

So the complete path became:

p.agila
│
│ MemberOf
▼
Service Account Managers
│
│ GenericAll
▼
Service Accounts
│
│ GenericWrite
▼
winrm_svc

winrm_svc was also a member of:

Remote Management Users

which made WinRM the relevant remote access mechanism once authentication as the account was obtained.

Shadow Credentials — First Attempt

Because Service Accounts had GenericWrite over winrm_svc, I tried to abuse the account using Shadow Credentials.

The idea behind Shadow Credentials is to add a new Key Credential to an AD account and then use the corresponding private key for authentication.

Press enter or click to view image in full size

However, my first attempt failed:

Could not update Key Credentials for 'winrm_svc' due to insufficient access rights
...
00002098
INSUFF_ACCESS_RIGHTS

Initially, this looked confusing because BloodHound clearly showed the GenericWrite relationship.

I went back through the attack path and checked the effective permissions.

The important detail was that p.agila was not yet a member of Service Accounts

Press enter or click to view image in full size

Therefore, although BloodHound showed:

Service Accounts
│
│ GenericWrite
▼
winrm_svc

that permission was not yet effective for my current security context.

Resolving the Permission Issue

The previous ACL in the chain was:

p.agila
│
▼
Service Account Managers
│
│ GenericAll
▼
Service Accounts

Since Service Account Managers had GenericAll over Service Accounts, I used that control to add p.agila to the Service Accounts group.

After the membership change, the effective path became:

p.agila
│
│ MemberOf
▼
Service Accounts
│
│ GenericWrite
▼
winrm_svc

This resolved the INSUFF_ACCESS_RIGHTS issue and allowed me to continue with the attack against winrm_svc

Press enter or click to view image in full size

Lesson Learned

This was one of the most useful parts of the machine for me.

BloodHound shows potential attack paths, but seeing an ACE does not necessarily mean that the final privilege is immediately usable.

When the Shadow Credentials attempt returned: INSUFF_ACCESS_RIGHTS

I went back through the graph and checked each relationship in the chain.

The actual problem was one step earlier in the path: I needed to obtain the effective group membership first.

winrm_svc and Remote Access

Once the required access to winrm_svc was established, the account's membership in:

Remote Management Users

provided the path to remote management through WinRM.

The attack path was therefore:

p.agila
↓
Service Account Managers
↓
GenericAll
↓
Service Accounts
↓
GenericWrite
↓
winrm_svc
↓
Remote Management Users
↓
WinRM

This allowed me to obtain the user-level foothold and retrieve:

user.txt

The interesting part here was that the initial account did not directly have administrative privileges.

Instead, the compromise was built through AD group relationships and delegated permissions.

Finding the Second Attack Path

Get Hadeer Amr’s stories in your inbox

Join Medium for free to get updates from this writer.

While analyzing the same Service Accounts group, I noticed another important relationship:

Service Accounts
│
│ GenericWrite
▼
ca_svc
Press enter or click to view image in full size

This was even more interesting because ca_svc was associated with:

Cert Publishers
Press enter or click to view image in full size

That suggested that the account could potentially be useful in an AD CS attack.

The attack path now had two branches:

                         Service Accounts
/ \
/ \
GenericWrite GenericWrite
/ \
▼ ▼
winrm_svc ca_svc
│ │
▼ ▼
WinRM AD CS
│ │
▼ ▼
user.txt ESC16

AD CS Enumeration

I then enumerated the Active Directory Certificate Services configuration using Certipy:

certipy-ad find -u 'p.agila@fluffy.htb' -p '[redacted]' -dc-ip 10.129.232.88 -target dc01.fluffy.htb -stdout
Press enter or click to view image in full size

The CA was:

CA Name: fluffy-DC01-CA
DNS Name: DC01.fluffy.htb

The most interesting finding was:

Disabled Extensions:
1.3.6.1.4.1.311.25.2

Understanding ESC16

The OID:

1.3.6.1.4.1.311.25.2

is associated with the SID Security Extension.

This extension is important because it provides a binding between a certificate and the security identity represented by the certificate.

In this environment, the extension was disabled globally on the CA.

Press enter or click to view image in full size

This configuration corresponds to:

ESC16

So instead of simply relying on Certipy’s vulnerability label, I could understand the actual misconfiguration:

SID Security Extension
│
│ Disabled globally
▼
CA misconfiguration
│
▼
ESC16

This was the key AD CS finding that connected ca_svc to the final privilege escalation.

Exploiting ca_svc

Since Service Accounts had GenericWrite over ca_svc, I could modify attributes of the account.

The goal was to manipulate the account’s UPN before requesting a certificate.

I used:

certipy-ad account update -u 'p.agila@fluffy.htb' -p '[redacted]' -dc-ip 10.129.232.88 -target 'dc01.fluffy.htb' -user 'ca_svc' -upn 'administrator'

The important output was:

[*] Updating user 'ca_svc': userPrincipalName : administrator
[*] Successfully updated 'ca_svc'

This was a particularly interesting moment because it demonstrated the practical impact of the GenericWrite permission.

The BloodHound relationship:

Service Accounts
│
│ GenericWrite
▼
ca_svc

was no longer just a graph edge.

It allowed me to modify the target account in a way that became useful for the AD CS attack.

The state was now:

ca_svc
│
│ UPN modified
▼
administrator

Certificate Request

The next step was to request a certificate from fluffy-DC01-CA

using the User template.

The command was:

certipy-ad req -u 'ca_svc@fluffy.htb' -hashes '<CA_SVC_NT_HASH>' -dc-ip 10.129.232.88 -target 'dc01.fluffy.htb' -ca 'fluffy-DC01-CA' -template 'User'

The request reached the RPC stage, but I encountered:

[*] Requesting certificate via RPC
[-] Got error: The NETBIOS connection with the remote host timed out.

So at this point, the certificate request itself had not successfully completed.

I would not describe the certificate issuance or Administrator authentication as completed until this connectivity issue is resolved.

The intended final ESC16 chain is:

ca_svc
│
│ UPN = administrator
▼
Certificate Request
│
▼
Administrator Certificate
│
▼
administrator.pfx
│
▼
Certificate Authentication
│
▼
Administrator
│
▼
root.txt

Final Attack Path

Putting everything together, the machine demonstrates two related privilege-escalation paths originating from the same AD group:

                         p.agila
│
│ MemberOf
▼
Service Account Managers
│
│ GenericAll
▼
Service Accounts
/ \
/ \
GenericWrite GenericWrite
/ \
▼ ▼
winrm_svc ca_svc
│ │
▼ ▼
Remote Management ESC16
Users │
│ ▼
▼ Administrator
WinRM │
│ ▼
▼ root.txt
user.txt

What I Learned

The most interesting part of this machine for me was not a single vulnerability, but understanding how multiple Active Directory permissions can be chained together.

The key concepts I practiced were:

BloodHound Attack Paths

Instead of looking at individual users and permissions, I learned to follow the complete relationship:

User
↓
Group
↓
ACL
↓
Target Object
↓
Authentication / Privilege

Effective Permissions

An ACE shown by BloodHound does not automatically mean that I can immediately exploit the final target.

The INSUFF_ACCESS_RIGHTS error was a good example.

I had to go back one step and make sure that the required group membership was actually effective.

GenericAll vs GenericWrite

I also got a clearer understanding of the difference between:

GenericAll

and:

GenericWrite

GenericAll provides broad control over an object, while GenericWrite allows modification of permitted attributes.

The impact depends on what object is being controlled and which attributes can be changed.

AD CS

The second major learning point was understanding that AD CS can become another privilege-escalation boundary inside an Active Directory environment.

In this case:

GenericWrite
↓
ca_svc
↓
AD CS
↓
SID Security Extension disabled
↓
ESC16

The important part was understanding why the configuration created an attack path rather than simply running Certipy and copying its output.

Conclusion

Fluffy was a good example of how an Active Directory compromise can develop through several layers of delegated access.

The attack did not depend on one obvious administrative credential.

Instead, the path was built through:

Initial Access
↓
Credential Discovery
↓
Active Directory Enumeration
↓
BloodHound
↓
GenericAll
↓
GenericWrite
↓
Service Account Control
↓
WinRM
↓
AD CS Enumeration
↓
ESC16
↓
Certificate-Based Privilege Escalation

The most valuable takeaway for me was learning to treat BloodHound as an attack-path analysis tool, rather than simply a tool for finding interesting ACEs.

When an exploitation attempt failed, such as INSUFF_ACCESS_RIGHTS the solution was not to randomly try another technique. I went back through the graph, identified which permission in the chain was not yet effective, fixed that prerequisite, and continued from there.

Thank You For Your Time

واخيرا اللهم علمني ما ينفعني و انفعني بما علمتني

Wishing This Is Helpful

--

--