Hack The Box - HTB SmartHire Writeup - Medium- Weekly - May 16th, 2026
SmartHire — Walkthrough
| Machine Detail | Value |
|---|---|
| Name | SmartHire |
| Difficulty | Medium |
| OS | Linux |
| Date | 05-16-2026 |
Introduction
SmartHire is a Linux-based target that demonstrates the risks of outdated MLOps infrastructure and insecure plugin architectures. The attack vector involves bypassing authentication on an outdated MLflow instance (version 2.14.1), achieving Remote Code Execution (RCE) via a tailored Pickle deserialization payload, and escalating privileges through a writable Python plugin directory used by a high-privilege management script.
Phase 1: Reconnaissance and Enumeration
Nmap Port Scanning
Initial discovery was conducted using Rustscan to identify open ports, followed by a detailed Nmap scan for service identification.
In professional penetration testing, controlling packet frequency is vital. The flags --min-rate and --max-rate were utilized to manage Packets Per Second (PPS). This ensures the scan remains efficient without overwhelming the target's network stack or triggering rate-limiting thresholds on Intrusion Detection Systems (IDS).
Open 10.129.XX.XX:22
Open 10.129.XX.XX:80
[~] Starting Script(s)
[>] Running script "nmap -vvv -p {{port}} -{{ipversion}} {{ip}} -A -oA smarthire.txt" on ip 10.129.XX.XX
Nmap service detection results:
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack 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 syn-ack nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://smarthire.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Two services were exposed: SSH (OpenSSH 8.9p1) on port 22 and HTTP (nginx 1.18.0) on port 80. The web server redirected to http://smarthire.htb/.
Web Enumeration
A direct curl request to the target IP resulted in a 302 redirect. To resolve this, the local /etc/hosts file was updated:
[IP_ADDRESS] smarthire.htb
Verify the redirect:
curl -vv $ip
Add the host entry:
sudo -- sh -c -e "echo \"$ip smarthire.htb\" >> /etc/hosts"
# or
echo "$ip smarthire.htb" | sudo tee -a /etc/hosts
To remove the last line of the file:
sudo sed -i '$ d' /etc/hosts
The landing page is the SmartHIRE site — an "AI-first evaluation platform powering high-trust hiring at scale," with About, Products, Testimonials, and Sign in navigation.
Directory Fuzzing
Run FFUF for additional pages:
ffuf -u http://smarthire.htb/FUZZ -w ~/git/SecLists/Discovery/Web-Content/common.txt -ac
Results:
dashboard [Status: 302, Size: 199, Words: 18, Lines: 6, Duration: 98ms]
logout [Status: 302, Size: 199, Words: 18, Lines: 6, Duration: 109ms]
login [Status: 200, Size: 6160, Words: 1357, Lines: 128, Duration: 142ms]
register [Status: 200, Size: 6499, Words: 1415, Lines: 132, Duration: 132ms]
Sub-Domain / V-Host Enumeration
ffuf -w /home/kali/git/SecLists/Discovery/DNS/subdomains-top1million-110000.txt \
-u http://smarthire.htb/ -H 'Host: FUZZ.smarthire.htb' -ac
Result:
models [Status: 401, Size: 137, Words: 11, Lines: 1, Duration: 147ms]
V-Host enumeration identified a subdomain: models.smarthire.htb. Update /etc/hosts to map both:
sudo sed -i '$ d' /etc/hosts
echo "$ip smarthire.htb models.smarthire.htb" | sudo tee -a /etc/hosts
Both domains were mapped to the target IP to allow proper interaction with the virtual hosts.
Application Analysis
The smarthire.htb dashboard provides "Train Model" and "Make Predictions" functionalities. These features utilize CSV uploads for processing. The models.smarthire.htb subdomain was identified as an instance of MLflow, a platform for the machine learning lifecycle.
Register
We can register for an account and log in to see the dashboard ("Welcome back, wind0!"). The dashboard exposes:
- Train Model — One-click training (upload hiring data CSV, max 2MB)
- Make Predictions — Score resumes
Both pages accept CSV in a specific format.
The models subdomain
The http://models.smarthire.htb subdomain is running MLflow. Some searching turns up CVE-2026-2635, an authentication bypass exploitable with the default credentials admin:password. This works, granting access.
We're running version 2.14.1, which is quite old (current version is 3.12). The next step is to search for known remote code execution vulnerabilities.
Phase 2: Exploiting MLflow for Initial Access
Authentication Bypass
The MLflow instance was identified as version 2.14.1, significantly outdated compared to current releases (e.g., 3.12). Research identified CVE-2026-2635, an authentication bypass vulnerability. Using the default credentials admin:password successfully granted access to the MLflow dashboard.
Vulnerability Research and Vector Selection
Several vulnerabilities were considered for the 2.14.1 environment:
- CVE-2025-15379 — Command injection via
python_env.yaml(requires specific environment managers). - CVE-2025-11201 — Directory traversal during model creation.
- CVE-2025-14287 — RCE via unsanitized container image names.
- CVE-2024-37055 — Deserialization of untrusted data.
- CVE-2024-2928 — Inapplicable (only affects versions < 2.11.2).
Given the "Make Predictions" feature on the main site, a Pickle deserialization attack was determined to be the most viable path.
Pickle Deserialization Attack (The "Mocked Utils" Hurdle)
Initial attempts to trigger RCE failed due to Python version mismatches and missing dependencies. Analysis of a legitimate python_model.pkl using unpickle.py and pickletools revealed that the model relied on a specific local structure: utils/simplehiringmodel.py.