Overview
SmartHire is a medium-difficulty Linux machine that simulates an AI-first hiring platform powered by an MLflow model management backend. The attack chain flows through three distinct stages:
Enumeration - discovering a hidden MLflow virtual host via subdomain fuzzing
Foothold - registering a malicious pickle model via the MLflow REST API to achieve remote code execution (RCE) as
svcweb, then using an artifact-based exfil technique to drop an SSH key (egress firewall bypassed entirely using localhost callbacks)Privilege Escalation - abusing a group-writable Python plugin directory and the
site.addsitedir/.pthexecution primitive to hijack a NOPASSWD sudo Python script and gain a root SUID shell
The machine teaches valuable lessons about ML pipeline security, Python import hijacking, and living-off-the-land in restricted-egress environments.
1. Enumeration
1.1 Full TCP Port Scan
nmap -sC -sV -T4 -p- --min-rate 5000 10.129.51.202
Output:
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.15 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 41:3c:e3:bb:88:70:99:7f:b8:96:59:48:9b:85:98:69 (ECDSA)
|_ 256 d5:9d:fd:6b:be:d8:39:6f:3f:43:ab:0e:f6:3e:22:db (ED25519)
80/tcp open http nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://smarthire.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Analysis:
Only two ports open - SSH and HTTP. The Nmap title shows that nginx performs a redirect to http://smarthire.htb/, indicating virtual host-based routing. All endpoints are served under this hostname, so it must be added to /etc/hosts before any further enumeration or browsing.
Flag: -p- ensures no ports are missed. --min-rate 5000 keeps the scan fast on HTB's network without sacrificing accuracy. -sC -sV grabs default NSE scripts and version banners, which is particularly useful for SSH hostkey fingerprinting and HTTP header analysis.
echo "10.129.51.202 smarthire.htb" | sudo tee -a /etc/hosts
1.2 Virtual Host (VHost) Fuzzing - Discovering MLflow
The main site being titled "SmartHIRE" and visually referencing ML pipelines suggests internal tooling may be exposed under a subdomain. We fuzz for virtual hosts using ffuf:
ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt \
-u http://smarthire.htb \
-H "Host: FUZZ.smarthire.htb" \
-fc 301,302
Output:
models [Status: 401, Size: 137, Words: 11, Lines: 1, Duration: 224ms]
:: Progress: [19966/19966] :: Job [1/1] :: 195 req/sec :: Duration: [0:01:40] :: Errors: 0 ::
Analysis:
The models subdomain returns HTTP 401 with a WWW-Authenticate: Basic realm="mlflow" header. This is a production MLflow tracking server hidden behind HTTP Basic Auth. MLflow is a popular open-source ML lifecycle platform that manages experiments, runs, and model artifacts.
Why this is critical: The main app has endpoints like /upload_hiring_data, /predict, and /model_info that interact with this MLflow instance. If we control what's in the model registry, we can inject a malicious model that executes code when the app calls load_model().
Add to hosts:
echo "10.129.51.202 models.smarthire.htb" | sudo tee -a /etc/hosts
🔐 PREMIUM WRITEUP - MEMBERSHIP REQUIRED
This machine is still active in HTB, so the full walkthrough, exploitation path, and flags cannot be publicly released.
But you can access the entire premium writeup right now.
🌟 Get Instant Access
Unlock the complete step-by-step solution, techniques used, notes, and exclusive insights by becoming a member.
Why Go Premium?
Early access to full detailed writeups
Passwords for active CTF solutions
Advanced exploitation techniques
Upgrade once - unlock everything instantly.
Keep hacking, keep learning, keep winning. 🎯

