Hack The Box: Horizontall

Jump Ahead: EnumUserRootResources


To solve this machine, we begin by enumerating open ports using nmap – finding ports 22 and 80 open. From the webserver, we find a subdomain through source code analysis. Doing some research on the platform we found on the subdomain, we learn that it contains a vulnerability within the password recovery mechanism. Exploiting the vulnerability, we are able to reset the administrator’s password, and gain administrative access to the platform. From our research, we also saw there was an authenticated RCE vulnerability that we are able to exploit to get a reverse shell as the strapi user – allowing access to user.txt. As strapi, we find an internal webserver that is also vulnerable to RCE. After exploiting the internal web server, get a reverse shell as root, and can read root.txt.


Like all machines, we begin by enumerating open ports using nmap. From our scans, we find ports 22 and 80 open.

$ sudo nmap -v -p- --min-rate 3000 $RHOST
$ sudo nmap -p 22,80 -sV -A -oA enum/nmap/tcp-scripts $RHOST
# Nmap 7.91 scan initiated Tue Aug 31 18:09:46 2021 as: nmap -p 22,80 -sV -A -oA enum/tcp-scripts
Nmap scan report for
Host is up (0.054s latency).

22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 ee:77:41:43:d4:82:bd:3e:6e:6e:50:cd:ff:6b:0d:d5 (RSA)
|   256 3a:d5:89:d5:da:95:59:d9:df:01:68:37:ca:d5:10:b0 (ECDSA)
|_  256 4a:00:04:b4:9d:29:e7:af:37:16:1b:4f:80:2d:98:94 (ED25519)
80/tcp open  http    nginx 1.14.0 (Ubuntu)
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: Did not follow redirect to http://horizontall.htb
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 4.15 - 5.6 (95%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 5.0 - 5.3 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 5.0 (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

1   53.65 ms

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Aug 31 18:09:59 2021 -- 1 IP address (1 host up) scanned in 12.82 seconds

Since port 80 is listening on the machine, we begin enumerating it using gobuster and nikto. Unfortunately, these tools do not provide any useful results. Next, we try to access the web server, but are redirected to horizontall.htb. Since this does not exist in our /etc/hosts file, nor is .htb a valid top-level domain, we are unable to access it. To get around this, we edit our /etc/hosts file to point the domain to the machine’s IP, and can now access the site.

Rerunning gobuster using the domain returns the same results as before, and looking around the site, all the links are dead. Since there is nothing obvious to look into, we decide to look through the different source files required for the site. By doing so, we hopefully will find something interesting. For this, we proxy our web requests through BurpSuite. Looking through the /js/app.c68eb462.js file, we find an interesting subdomain – api-prod.horizontall.htb.

After adding the subdomain to our /etc/hosts file, we are able to see the endpoint the JavaScript file referenced.

Once again, we launch gobuster on the newly discovered subdomain, and find several interesting directories.

$ for i in files directories; do gobuster dir -t 30 -u http://api-prod.horizontall.htb -w /opt/wordlists/seclists/Discovery/Web-Content/raft-medium-$i.txt -o enum/web/gobuster-80-api-prod-rm${i:0:1}.txt; done
/admin                (Status: 200) [Size: 854]
/Admin                (Status: 200) [Size: 854]
/users                (Status: 403) [Size: 60]
/reviews              (Status: 200) [Size: 507]
/ADMIN                (Status: 200) [Size: 854]
/Users                (Status: 403) [Size: 60]
/Reviews              (Status: 200) [Size: 507]

When we try to access the /admin directory, we are redirected to http://api-prod.horizontall.htb/admin/auth/login where we are presented with a login form for “strapi”.

Getting User

As we do not see a way forward other than Strapi, we decide to Google for “strapi vulnerabilities”. In doing so, we find this CVE list that gives us some ideas of things to look into. From the list, CVE-2019-18818 sounds the most promising, as it appears to be a vulnerability within the password reset functionality. After some research into this CVE, we find this blog post that details an exploit for resetting a user’s password. Since this seems easy enough, we download the script to try to use it against the remote machine. As we are unaware of the admin’s email address, we make the guess of “admin@horizontall.htb”, and attempt to use the script. When we run the script, we are given a message that appears our password reset was successful.

Going back to the login form, we attempt to use the email address and password to login, and are successful. We now have access to the admin interface as admin.

From our previous research of Strapi vulnerabilities, we saw there may potentially be an authenticated remote code execution vulnerability in the install and uninstall plugin components (CVE-2019-19609). From its CVE details page, we are linked to this article that outlines the vulnerability and demonstrates an exploit to get a reverse shell. Using the curl proof-of-concept exploit command, we update the relevant headers, and update the data to use our IP and chosen port. Additionally, we remove the “Content-Length” header, as it may no longer be valid for our use. Before we execute the command, we start a netcat listener to accept the connection. Finally, we run the command and get a reverse shell as strapi. Looking around the machine for user.txt, we find it in /user/developer/, and see that we can also read it.

Getting Root

Since we have a shell on the machine as strapi, we start looking for ways to privilege escalate. To do this, we run LinPEAS, and one thing we see is that there is a service running locally on port 8000.

Since we do not know what is running on the port, we decide to run curl to check if it is a webserver. Running it, we get a response that indicates it is a webserver hosting Laravel.

Rather than upload a bunch of tools to the machine to enumerate the webserver, we decide to use chisel to forward the machines port 8000 to our local machine on port 8000.

After we create the port forward, we open the webserver in our browser, and confirm it is hosting Laravel version 8.

Next, for a quick check, we run searchsploit to check if there are any vulnerabilities for version 8 of Laravel. Doing so, we see there is one for Remote Code Execution. When we run the tool, we see that we also need the path to the log.

Looking at hacktricks, we learn that we can get the path of Laravel if it is in debug mode by going to /profiles. Going to, we indeed learn the path is at /home/developer/myproject/.

Now that we have the log path, we execute the exploit. Attempting to get a reverse shell, we are successful, and get a shell as root – allowing us to now read root.txt.

Thank you for taking the time to read my write-up. I am interested in other ways this machine has been solved. Feel free to reach out to me and we can discuss it. Thanks!