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

Code

22 Mar 2025 · 16 min read · root access
Code HTB machine

Executive summary — Code is an Easy Linux box whose entry point is an online Python code editor (Flask on Gunicorn) that runs your input after filtering it through a keyword blocklist. We escape the sandbox by pulling the already-loaded modules from globals() and using getattr() to reach os.popen without ever writing the forbidden words literally (RCE). The application's SQLite database holds unsalted MD5 hashes; we crack martin's and log in over SSH. Root comes from a sudo NOPASSWD entry on backy.sh, a backup wrapper whose anti-traversal filter (../) does a single pass and is bypassed with ....// to archive the whole of /root. Path: web sandbox → RCE → SQLite → SSH → backy.sh → root.

PlatformHack The Box
Operating systemLinux
DifficultyEasy
StatusRetired
Target IP10.10.11.62

Attack map

[5000/HTTP] "Python Code Editor" (Flask + Gunicorn)
   │  runs Python with a keyword BLOCKLIST (import, os, eval…)
   │  sandbox escape: globals()['o'+'s'] + getattr() → os.popen
   ▼
[RCE]  shell as app-production
   │  SQLite instance/database.db → MD5 hashes (development, martin)
   │  crack martin → nafeelswordsmaster
   ▼
[SSH]  martin  (user.txt)
   │  sudo -l → NOPASSWD /usr/bin/backy.sh
   │  «../» filter bypassed with «....//»  → archive /root
   ▼
[ROOT]

1. Recon

As usual, we start with a full sweep of all 65535 TCP ports, then a targeted script and version scan on whatever comes back open:

nmap -p- --min-rate 10000 10.10.11.62
nmap -p22,5000 -sCV 10.10.11.62
22/tcp   open  ssh      OpenSSH 8.2p1 Ubuntu
5000/tcp open  http     Gunicorn 20.0.4

--min-rate 10000 forces nmap to send packets at a high minimum rate so sweeping the entire port range doesn't take forever; -sCV is shorthand for -sC -sV (default NSE scripts + version detection) run only against the ports we already know are open.

Only two ports: SSH (no credentials yet, so not the entry vector) and an HTTP service on 5000 served by Gunicorn, the production WSGI server typical of Python/Flask apps (the Flask dev server normally isn't fronted by Gunicorn on port 5000). The whole foothold necessarily goes through 5000.

🔒 Clearance required

This content is Root Access only. Everything else on the site — the free tier, the whole public library — stays open.

See Root Access plans

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