文章总结: 文档分析CVE-2026-39987漏洞,指出Marimo的WebSocket端点/terminal/ws因缺失身份验证检查,允许未授权攻击者连接后获得完整shell并执行任意系统命令。作者通过代码对比显示该漏洞源于认证逻辑遗漏,并详细描述了从连接到获取root权限的攻击链。文末提供官方修复参考链接。 综合评分: 85 文章分类: 漏洞分析,WEB安全,应用安全,红队,安全开发
我的洞火了?那就讲讲吧
原创
秋风 秋风
秋风的安全之路
2026年4月16日 20:08 广东
在小说阅读器读本章
去阅读
CVE-2026-39987相信有部分师傅应该刷到了
不管是网页还是x还是公众号还是比较多人发的
这个洞其实并非很复杂
Marimo 的终端 WebSocket 端点 /terminal/ws 缺少身份认证检查,允许任何人(包括未认证的攻击者)直接连接并获得一个完整的 shell,从而执行任意系统命令
可以看到:
# marimo/_server/api/endpoints/terminal.py (第 340-356 行)@router.websocket("/ws")async def websocket_endpoint(websocket: WebSocket) -> None: app_state = AppState(websocket)
if app_state.mode != SessionMode.EDIT: await websocket.close(...) return
if not supports_terminal(): await websocket.close(...) return
await websocket.accept()
child_pid, fd = pty.fork()
这我觉得很明显是遗忘了
可以看到他另一处的处理
#ws_endpoint.py (第 67-82 行)@router.websocket("/ws")async def websocket_endpoint(websocket: WebSocket) -> None: app_state = AppState(websocket) validator = WebSocketConnectionValidator(websocket, app_state)
if not await validator.validate_auth(): return
调用了validate_auth()进行身份的验证
Marimo 使用 Starlette 的 AuthenticationMiddleware,有一个局限性就是它会将失败的认证标记为UnauthenticatedUser,但是不会拒绝WebSocket的连接,实际需要@requires()或者validate_auth()方法
所以就有了如下攻击链:
1. 连接 ws://目标服务器:2718/terminal/ws (无需任何认证) ↓2. 服务器直接调用 websocket.accept() 接受连接 ↓3. 调用 pty.fork() 创建伪终端子进程 ↓4. 获得完整的交互式 shell ↓5. 可以执行任意系统命令 ↓6. root
ref:
https://github.com/marimo-team/marimo/security/advisories/GHSA-2679-6mx9-h9xc
https://links.marimo.app/cwe-306-terminal-ws-auth-bypass
https://github.com/marimo-team/marimo/security
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:秋风的安全之路 秋风 秋风《我的洞火了?那就讲讲吧》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论