root@thehacksparrow:~/writeups$ SYSTEM ONLINE
root@sparrow:~/writeups$ cat celestial.md
// writeups

Celestial

10 Mar 2018 · 9 min read · root access
Celestial - maquina de Hack The Box

Executive summary — Celestial exposes a single Node.js/Express application on port 3000 that stores user state in a base64-encoded profile cookie. That cookie is a JSON object the app deserializes server-side with node-serialize, vulnerable to CVE-2017-5941: embedding a function behind a special marker is enough to get it executed as arbitrary code during deserialization itself. That hands over a shell as the sun user (user.txt); from there, a root cron running a Python script owned by —and therefore writable by— sun allows swapping it for a payload that, once the cron fires, drops a SUID shell and delivers root.txt.

PlatformHack The Box
Operating systemLinux (Ubuntu)
DifficultyMedium
StatusRetired
Target IP10.129.228.94
Exposed service3000/tcp — Node.js Express

Attack map

[3000/tcp] Node.js Express -> `profile` cookie (base64 JSON, reflected back)
   │  CVE-2017-5941 (node-serialize): _$$ND_FUNC$$_...() payload in "username"
   ▼
IIFE executed DURING unserialize() -> reverse shell
   │
   ▼
[USER] sun (uid=1000)                                   <- user.txt
   │  root cron runs /home/sun/Documents/script.py (owned by sun, writable)
   ▼
script.py replaced with a Python payload -> SUID /tmp/rootbash
   ▼
[ROOT] /tmp/rootbash -p                                 <- root.txt

1. Reconnaissance

sudo nmap -p- --min-rate 2000 -T4 -Pn 10.129.228.94 -oN nmap/allports.txt
sudo nmap -p 3000 -sCV -Pn 10.129.228.94 -oN nmap/svc.txt
3000/tcp open  http  Node.js Express framework

A single open port across the whole range: the attack surface is, necessarily, that Express app. The HTTP response carries a cookie worth a second look:

Set-Cookie: profile=eyJ1c2VybmFtZSI6IkR1bW15Ii...  (HttpOnly)
X-Powered-By: Express
echo 'eyJ1c2VybmFtZSI6IkR1bW15Ii...' | base64 -d
# {"username":"Dummy","country":"Idk Probably Somewhere Dumb","city":"Lametown","num":"2"}

Sending that same cookie back, the app reflects the fields in the response:

curl -s http://10.129.228.94:3000/ -b 'profile=<base64>'
# Hey Dummy 2 + 2 is 22

A base64 cookie that decodes to JSON and that the server processes server-side — not just reads, but reconstructs an object from — is the classic signature of insecure deserialization in Node.js. The library most associated with this pattern is node-serialize, which doesn't just reconstruct data: it also knows how to reconstruct serialized functions, which is the root of the issue.

🔒 Clearance required

Root Access unlocks the content you can't see — everything else on the site is already open.

See Root Access plans

No account? Create one free then upgrade from your console.