Baby
Overview
Baby is an easy-difficulty Windows Active Directory machine on HTB that demonstrates a classic and realistic misconfiguration chain found in real enterprise environments. The entire attack path flows naturally from a single initial mistake - a password left in an LDAP user description field - and escalates through a well-known but powerful Windows privilege abuse to achieve full domain compromise.
The attack begins with unauthenticated LDAP enumeration. The domain allows anonymous LDAP binds, which is a common misconfiguration in legacy or improperly hardened Active Directory deployments. Querying the directory for user objects reveals a plaintext password stored in a user's description attribute - a habit some administrators develop when onboarding new accounts, leaving default passwords in the directory instead of communicating them securely. We harvest the full user list from LDAP, then password-spray the discovered credential across all accounts.
One account - Caroline.Robinson - matches the password but is flagged as requiring a password change at next logon. We satisfy this requirement using smbpasswd to set a new password of our choosing, which immediately grants us full authenticated domain access. Caroline turns out to be a member of the Backup Operators built-in group and the Remote Management Users group, allowing us to connect via WinRM for an interactive session and obtain the user flag.
The privilege escalation path flows directly from the SeBackupPrivilege that Backup Operators hold. This privilege grants the ability to read any file on the system regardless of ACL - it's intended to allow backup software to read locked or restricted files without being a domain admin. We abuse it first to dump the SAM and SYSTEM registry hives, and then to extract the NTDS.dit database from a Volume Shadow Copy created via diskshadow. Dumping NTDS.dit offline with impacket-secretsdump yields the NTLM hashes for all domain users, including the Administrator and other privileged accounts, completing the compromise.
Difficulty: Easy
OS: Windows (Active Directory / HTB)
Key Skills: Anonymous LDAP enumeration, credential discovery in user attributes, password spraying, forced password change via smbpasswd, BloodHound AD enumeration, WinRM access, SeBackupPrivilege abuse, Volume Shadow Copy via diskshadow, NTDS.dit extraction, offline hash dumping.
Recon
Port Scanning with Nmap
We begin with a standard Nmap service and script scan, followed by a full port scan across all 65535 ports. Running both concurrently saves time - the targeted scan returns quickly and gives us immediate visibility while the full port sweep continues in the background.
sudo nmap -sC -sV -vv -oA tcp 10.129.234.71; sudo nmap -sC -sV -vv -p- -oA allports 10.129.234.71The results confirm this is a Windows domain controller. The open ports include 88 (Kerberos), 135 (RPC), 139/445 (SMB), 389/636 (LDAP/LDAPS), 3268/3269 (Global Catalog), and 5985 (WinRM). The Nmap scripts also resolve the hostname, revealing the machine's fully qualified domain name: babydc.baby.vl. We add both babydc.baby.vl and baby.vl to our /etc/hosts file to ensure proper DNS resolution throughout the engagement.
The presence of WinRM on port 5985 is immediately noted - if we obtain valid domain credentials for a user in the Remote Management Users group, we have a direct path to an interactive shell without needing to exploit any additional services.
LDAP Enumeration with NetExec
With a domain name in hand, we probe LDAP using nxc (NetExec). A critical misconfiguration in many Active Directory environments is allowing unauthenticated (anonymous) LDAP binds, which lets anyone query the directory without credentials. We attempt an anonymous LDAP enumeration to see what information the domain exposes publicly.
The query succeeds without any credentials, and within the results we find something immediately valuable: a plaintext password stored in a user's description attribute. Storing passwords in description fields is a bad practice that administrators sometimes use during account provisioning - they put a default or temporary password in the description so the new user can find it, intending to have it changed later. These are frequently forgotten and left indefinitely, and because description fields are readable by all authenticated (and sometimes unauthenticated) users, they become a trivial credential disclosure vulnerability.
Full LDAP User Enumeration
The nxc output gives us a partial view of the directory. To get the complete picture, we run a raw ldapsearch query targeting all user objects in the domain and dump the full output to a file for processing:
ldapsearch -x -H ldap://BabyDC.baby.vl -b 'DC=baby,DC=vl' '(objectClass=user)'The filtered output matches what nxc already showed us, so we broaden the query further to pull all LDAP attributes and objects in one pass, giving us a comprehensive dump of the directory:
ldapsearch -x -H ldap://BabyDC.baby.vl -b 'DC=baby,DC=vl' '*' > ldap_users_2With the full LDAP dump saved, we sanitise the output to extract just the usernames from the distinguished name (dn) fields. We pipe through grep to isolate dn: lines, then use cut to strip the CN= prefix and the trailing domain components, leaving us with clean usernames:
cat ldap_users_2 | grep "dn: " | cut -d '=' -f 2 | cut -d "," -f 1 > users_ldapAfter removing computer accounts, built-in groups, and other non-user objects by cross-referencing with the original output, we have the following list of domain user accounts:
Jacqueline.Barnett
Ashley.Webb
Hugh.George
Leonard.Dyer
Ian.Walker
Connor.Wilkinson
Joseph.Hughes
Kerry.Wilson
Teresa.Bell
Caroline.RobinsonThis gives us a clean target list of ten user accounts to spray our discovered password against.
Foothold
Password Spraying
With a list of valid domain users and a candidate password discovered from the LDAP description field, we perform a password spray using nxc against LDAP. A spray - testing one password against many users - is preferable to brute-forcing individual accounts because it avoids triggering account lockout policies, which typically lock an account after a fixed number of failed attempts per user, not per source IP.
nxc ldap baby.vl -u users_ldap -p passThe spray returns a hit for Caroline.Robinson, but with an important caveat: the authentication attempt returns a STATUS_PASSWORD_MUST_CHANGE error rather than a clean success. This means the account exists, the password is correct, but a password change is required before the account can be fully used - a flag Active Directory sets on newly provisioned accounts or when an admin manually forces a reset. This is actually a common scenario when credentials are discovered from a description field, since those passwords are often set as temporary credentials for new users.
Forced Password Change via smbpasswd
The STATUS_PASSWORD_MUST_CHANGE condition can be resolved without logging into the machine. The SMB protocol supports a password change operation that can be triggered remotely - the smbpasswd utility with the -r flag connects to the domain controller over SMB and performs the password change after providing the current (known) password and setting a new one:
smbpasswd -r baby.vl -U Caroline.Robinsonsmbpasswd prompts us for Caroline's old password (the one found in the LDAP description), then asks for and confirms a new password of our choosing. The password change succeeds, and the STATUS_PASSWORD_MUST_CHANGE flag is cleared. Caroline's account is now fully accessible with the new password we set.
BloodHound Active Directory Enumeration
Before connecting as Caroline, we run a BloodHound collection to map the full Active Directory environment. BloodHound uses graph theory to model relationships between AD objects - users, groups, computers, GPOs, and ACLs - and can reveal non-obvious privilege escalation paths that would be tedious to discover through manual enumeration. We use bloodhound-ce-python, the Community Edition Python ingestor, which runs the collection from our attack machine without needing to touch the target:
bloodhound-ce-python -d baby.vl -c All --zip -dc babydc.baby.vl --dns-tcp -ns 10.129.234.71 -u Caroline.Robinson -p 'syk0123!'The BloodHound data confirms that Caroline is a member of three notable groups:
- IT - a custom department group, likely with additional resource access
- Remote Management Users - grants the right to authenticate via WinRM (Windows Remote Management / PowerShell remoting), meaning we can open an interactive shell directly
- Backup Operators - a powerful built-in Windows group that grants
SeBackupPrivilegeandSeRestorePrivilege, allowing the holder to read and write any file on the system regardless of NTFS permissions
The Backup Operators membership is the critical finding. This group exists specifically to allow backup software to read protected files without requiring full administrative access, but the same privileges can be abused by an attacker to read sensitive files like NTDS.dit or the SAM/SYSTEM hives.
WinRM Access and User Flag
With Caroline in the Remote Management Users group and WinRM confirmed open on port 5985, we connect using evil-winrm-py for an interactive PowerShell session:
evil-winrm-py -i baby.vl -u Caroline.Robinson -p 'syk0123!'The connection succeeds and we land in an interactive shell as Caroline.Robinson. We navigate to her desktop and retrieve the user flag, completing the first objective.
Privilege Escalation
Enumerating Caroline's Privileges
With a shell as Caroline, we check the token privileges assigned to her session. As a member of Backup Operators, she inherits the backup and restore privileges that define the group's purpose:
SeBackupPrivilege is confirmed as enabled. This privilege instructs the Windows kernel to bypass normal DACL-based access checks when the holder opens a file with the backup intent flags set. In practical terms, it means Caroline can read any file on the local system - including files that are normally locked to SYSTEM or Administrator access only, such as the registry hives and Active Directory database. This is exactly what we need to extract credentials for more privileged accounts.
Dumping the SAM and SYSTEM Registry Hives
The first approach is to dump the SAM and SYSTEM registry hives. The SAM (Security Accounts Manager) database stores NTLM hashes for local accounts, including the local Administrator account. The SYSTEM hive contains the boot key needed to decrypt the SAM. Together, they allow offline extraction of local account hashes. We use reg save to export both hives to disk from within our WinRM session:
reg save HKLM\sam sam
reg save HKLM\system systemWe download both files to our attack machine and run impacket-secretsdump in local mode to decrypt the hashes offline:
impacket-secretsdump -sam sam -system system LOCALThe dump succeeds and reveals the local Administrator's NTLM hash. However, when we attempt to use this hash for a Pass-the-Hash WinRM login, it fails. The built-in Administrator account is blocked from WinRM access, a restriction enforced by the LocalAccountTokenFilterPolicy setting - local accounts (as opposed to domain accounts) have their tokens filtered by UAC even when using Pass-the-Hash, effectively preventing remote administrative access unless specifically configured otherwise.
We need to go deeper: rather than the local Administrator, we should target a domain account with administrative privileges. BloodHound data shows that Ian.Walker is a member of the domain Administrators group, making him the ideal target. To get Ian's hash, we need the NTDS.dit file - the Active Directory database that stores credentials for all domain accounts.
Extracting NTDS.dit via Volume Shadow Copy
NTDS.dit is the crown jewel of any Active Directory environment. It contains the NTLM hashes (and optionally Kerberos keys) for every domain account - users, computers, and service accounts alike. The file is located at C:\Windows\NTDS\NTDS.dit and is kept open and locked by the Active Directory Domain Services process at all times, meaning it cannot simply be copied while the system is running. However, SeBackupPrivilege gives us a way around both the lock and the access restriction.
The standard technique is to use the built-in Windows diskshadow.exe utility to create a Volume Shadow Copy (VSS) of the C: drive. A VSS snapshot captures a point-in-time, read-consistent image of the volume - crucially, it includes a copy of NTDS.dit that is not locked, because the snapshot was made while the VSS writer for Active Directory flushed the database to a consistent state. We then expose the shadow copy as a separate drive letter and use robocopy in backup mode (which honours SeBackupPrivilege) to copy the file out.
We create a diskshadow script file. The script enables verbose output, sets a metadata path, configures a persistent backup context, adds the C: volume as the backup target, creates the snapshot, and exposes it as drive letter F:. It is critical to ensure the script file uses Windows-style CRLF line endings - diskshadow is sensitive to line endings and will silently fail or misparse commands if the file uses Unix LF endings:
SET VERBOSE ON
SET METADATA C:\Windows\Temp\meta.cab
SET CONTEXT PERSISTENT
BEGIN BACKUP
ADD VOLUME C: ALIAS cdrive
CREATE
EXPOSE %cdrive% F:
END BACKUP
EXITWe upload the script and execute it via diskshadow:
The shadow copy is created and exposed as F:\. The Active Directory database is now accessible at F:\Windows\NTDS\NTDS.dit as an unlocked snapshot. We use robocopy with the /B flag, which enables backup mode and invokes SeBackupPrivilege to bypass ACL restrictions on the source files:
robocopy /B F:\Windows\NTDS\ .\ntdsrobocopy successfully copies the entire NTDS directory - including NTDS.dit and the transaction log files - to our working directory. We also need the SYSTEM hive we extracted earlier, as it contains the boot key used to decrypt the NTDS.dit database. We download both files to our attack machine.
Dumping All Domain Hashes
With NTDS.dit and the SYSTEM hive in hand, we run impacket-secretsdump in local offline mode, pointing it at the NTDS database:
impacket-secretsdump -ntds ntds.dit -system system LOCALsecretsdump decrypts the database using the boot key from the SYSTEM hive and outputs the NTLM hash for every domain account - users, computers, and the domain Administrator. We now have Ian.Walker's NTLM hash, which we can use for Pass-the-Hash authentication via evil-winrm-py:
evil-winrm-py -i baby.vl -u Ian.Walker -H <NTLM_HASH>Ian is a member of the domain Administrators group, granting full administrative access to the domain controller. We retrieve the root flag from the Administrator's desktop, completing the machine.

