keraattin/CVE-2026-39987

GitHub: keraattin/CVE-2026-39987

该项目提供针对 Marimo 预认证 RCE 漏洞的检测与缓解指导,帮助识别和修复关键身份验证绕过问题。

Stars: 0 | Forks: 0

# CVE-2026-39987 — Marimo Python Notebook 预认证远程代码执行

CVE-2026-39987 CVSS 9.3 CWE-306 Marimo Pre-Auth RCE

## TL;DR Marimo 中存在一个**预认证远程代码执行**漏洞,这是一款用于数据科学和 AI/ML 的开源 Python 笔记本。关键终端 WebSocket 端点(`/terminal/ws`)完全**跳过身份验证**,而相邻笔记本端点(`/ws`)则正确执行验证。未经身份验证的攻击者可以连接到 `/terminal/ws` 并获得主机的**完整交互式 PTY Shell**,无需任何凭据。 在披露后 **10 小时内** 已在野外被利用。攻击者在 **3 分钟** 内窃取了 AWS 凭据。 **影响 Marimo <= 0.20.4。在 Marimo 0.23.0 中已修复。** ## 目录 - [Quick Facts](#quick-facts) - [What is Marimo?](#what-is-marimo) - [Vulnerability Deep Dive](#vulnerability-deep-dive) - [The Two WebSocket Endpoints](#the-two-websocket-endpoints) - [The Missing Auth Check](#the-missing-auth-check) - [The Attack: Advisory to AWS Keys in 3 Minutes](#the-attack-advisory-to-aws-keys-in-3-minutes) - [Impact Analysis](#impact-analysis) - [Affected Versions](#affected-versions) - [The Bigger Picture: AI/ML Toolchain Under Attack](#the-bigger-picture-aiml-toolchain-under-attack) - [Detection](#detection) - [Python Scanner](#python-scanner) - [Nmap NSE Script](#nmap-nse-script) - [Manual Verification](#manual-verification) - [Indicators of Compromise](#indicators-of-compromise) - [Remediation](#remediation) - [References](#references) - [Author](#author) ## 快速要点 | Field | Detail | |-------|--------| | **CVE ID** | CVE-2026-39987 | | **Vendor** | Marimo Project | | **Product** | Marimo (Python Notebook) | | **Affected Versions** | <= 0.20.4 | | **CVSS v3.1** | 9.3 (Critical) | | **CWE** | CWE-306 — Missing Authentication for Critical Function | | **Attack Vector** | Network | | **Authentication** | None required | | **User Interaction** | None | | **Exploit Maturity** | Actively exploited in the wild | | **Time to Exploitation** | ~10 hours after disclosure | | **Patched In** | Marimo 0.23.0 | ## 什么是 Marimo? Marimo 是一个开源的响应式 Python 笔记本,旨在作为 Jupyter 的现代替代品。它专为数据科学、AI/ML 实验和交互式数据分析而构建。其主要特性包括自动依赖跟踪、可重复执行以及比传统笔记本更佳的开发者体验。 Marimo 在 Python 和 AI/ML 社区中迅速获得 traction,尤其受到那些希望获得比 Jupyter 更结构化笔记本工作流程的从业者青睐。 与所有笔记本环境一样,Marimo 实例通常可以访问敏感资源:云凭据(AWS、GCP、Azure)、数据库连接字符串、AI 服务的 API 密钥(OpenAI、Anthropic 等)以及内部网络访问。与传统 Web 应用程序不同,笔记本**设计用于执行任意代码**,这正是其核心目的。 这种组合使得任何身份验证绕过在笔记本环境中都特别具有破坏性。 ``` Typical Marimo Deployment: ┌──────────────┐ ┌────────────────────────────────┐ │ │ HTTP │ Marimo Server │ │ Browser │────────>│ │ │ (User) │ │ ┌──────────────────────────┐ │ │ │<────────│ │ /ws (Notebook) │ │ └──────────────┘ WS │ │ ✅ validate_auth() │ │ │ └──────────────────────────┘ │ │ │ │ ┌──────────────────────────┐ │ │ │ /terminal/ws │ │ │ │ ❌ NO AUTH CHECK │ │ │ └──────────────────────────┘ │ │ │ │ ┌──────────────────────────┐ │ │ │ Python Environment │ │ │ │ .env files │ │ │ │ AWS credentials │ │ │ │ API keys │ │ │ └──────────────────────────┘ │ └────────────────────────────────┘ ``` ## 漏洞深度分析 ### 两个 WebSocket 端点 Marimo 的服务器为不同功能实现了多个 WebSocket 端点。两个主要端点之间的关键区别在于是否存在身份验证检查: ``` Authentication Flow Comparison: /ws (Notebook WebSocket): ┌─────────┐ ┌───────────────┐ ┌──────────┐ ┌───────────┐ │ Connect │───>│ validate_auth │───>│ Accept │───>│ Notebook │ └─────────┘ └───────┬───────┘ └──────────┘ └───────────┘ │ ❌ Reject if not authenticated /terminal/ws (Terminal WebSocket): ┌─────────┐ ┌───────────────┐ ┌──────────┐ ┌───────────┐ │ Connect │───>│ Check mode & │───>│ Accept │───>│ PTY Shell │ └─────────┘ │ platform only │ └──────────┘ └───────────┘ └───────────────┘ ⚠️ No auth check! Anyone gets a shell! ``` ### 缺失的认证检查 笔记本端点(`/ws`)正确调用 `validate_auth()` 来在建立 WebSocket 连接前验证用户身份。这是预期的安全行为。 终端端点(`/terminal/ws`)仅检查服务器是否处于运行模式以及平台是否支持终端功能。**从未调用 `validate_auth()`**。在通过这些基本检查后,它接受连接并创建一个完整的 PTY(伪终端)会话。 ``` # /ws(笔记本)— 正确实现 async def websocket_connect(self, message): await self.validate_auth() # ✅ Checks authentication await self.accept() # ... notebook communication # /terminal/ws(终端)— 漏洞实现 async def websocket_connect(self, message): if not self.is_running_mode(): # Only checks mode await self.close() return if not self.is_platform_supported(): # Only checks platform await self.close() return await self.accept() # ❌ No auth! Anyone gets a shell # ... PTY shell creation ``` 这属于 **CWE-306:关键功能缺少身份验证**。服务器上最危险的端点(提供交互式 Shell)完全没有身份验证。 ### 攻击:三分钟内获取 AWS 密钥 利用时间线显示了现代威胁行动者的运作速度: ``` ┌──────────────────────────────────────────────────────────────┐ │ CVE-2026-39987 Timeline │ ├──────────────────────────────────────────────────────────────┤ │ │ │ T+0h Advisory published │ │ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ │ T+9h First exploit built from advisory │ │ T+10h Exploitation in the wild confirmed │ │ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ │ T+10h 0m Attacker connects to /terminal/ws │ │ T+10h 1m Full PTY shell obtained │ │ T+10h 2m .env file located and read │ │ T+10h 3m AWS keys exfiltrated │ │ Total attack time: ~3 minutes │ └──────────────────────────────────────────────────────────────┘ ``` 攻击本身极其简单: ``` Step 1: Attacker opens WebSocket connection to /terminal/ws (No authentication needed, no special tools required) Step 2: Server creates a PTY (pseudo-terminal) session Attacker now has an interactive shell Step 3: Attacker runs commands: $ cat .env AWS_ACCESS_KEY_ID=AKIA... AWS_SECRET_ACCESS_KEY=... DATABASE_URL=postgres://... OPENAI_API_KEY=sk-... Step 4: Credentials exfiltrated Attacker now has cloud access, database access, and API keys for AI services Total time: under 3 minutes Authentication required: none Tools required: any WebSocket client ``` 无需开发利用程序、无需 Shellcode、无需内存损坏。只需要一个 WebSocket 客户端和一个缺失的身份验证检查。 ## 影响分析 **对 Marimo 主机的即时影响:** - 具有 Marimo 进程权限的完整交互式 Shell - 访问进程可读的所有文件(源代码、数据、凭据) - 访问包含 API 密钥和密钥的环境变量 - 在主机系统上执行任意命令的能力 **凭据暴露(主要攻击目标):** - 从 `.env` 文件或环境变量中获取的 AWS 访问密钥和秘密密钥 - GCP/Azure 服务账户凭据 - 包含密码的数据库连接字符串 - OpenAI、Anthropic 等 AI 服务的 API 密钥 - SSH 密钥及其他认证材料 **通过窃取凭据产生的下游影响:** - 未授权访问云基础设施(EC2、S3、Lambda 等) - 从云存储和数据库中提取数据 - 资源滥用(加密货币挖掘、AI API 信用盗窃) - 横向移动进入云和本地网络 **风险放大因素:** - 笔记本环境设计用于执行任意代码(这是其设计目的) - 数据科学环境通常拥有用于训练任务的广泛云访问权限 - 许多 Marimo 实例为协作和远程工作而暴露于互联网 - 安全加固在研究/实验环境中往往被忽视 ## 受影响版本 | Version | Status | |---------|--------| | Marimo 0.23.0+ | **Patched** | | Marimo 0.20.5 到 0.22.x | **Likely vulnerable**(在披露范围与修复版本之间) | | Marimo <= 0.20.4 | **Vulnerable**(确认范围) | ## 更大的图景:AI/ML 工具链受到攻击 CVE-2026-39987 并非孤立事件。这是 2026 年 4 月出现的一个明确模式的一部分: | CVE | Product | Type | Status | |:---|:---|:---|:---| | **CVE-2026-39987** | Marimo | Pre-Auth RCE (WebSocket) | Exploited in 10 hours | | **CVE-2026-33017** | Langflow | RCE | CISA KEV (March 26) | | **CVE-2026-5059** | aws-mcp-server | Command Injection RCE | Public advisory | | **TorchGeo** | TorchGeo | eval() RCE | Public advisory | 四个 AI/ML 开发工具在一个月内接连遭遇关键 RCE 漏洞。AI/ML 开发流程正在成为新的影子 IT:在这些工具被部署时往往拥有广泛访问权限、最小安全监督以及丰富的凭据存储。 ``` ┌─────────────────────────────────────────────────┐ │ Why AI/ML Tools Are Prime Targets │ ├─────────────────────────────────────────────────┤ │ │ │ 1. DESIGNED to execute arbitrary code │ │ (that's literally what notebooks do) │ │ │ │ 2. Run with elevated privileges │ │ (GPU access, cloud SDKs, network access) │ │ │ │ 3. Contain high-value credentials │ │ (AWS keys, API tokens, DB connections) │ │ │ │ 4. Often exposed to the network │ │ (for collaboration and remote access) │ │ │ │ 5. Security hardening is an afterthought │ │ (focus on features and UX, not security) │ │ │ │ 6. Users are researchers, not security experts │ │ (default configs, weak passwords, no VPN) │ └─────────────────────────────────────────────────┘ ``` ## 检测 ### Python 扫描器 Python 脚本通过多步骤分析来检测易受攻击的 Marimo 实例。 **工作原理:** 1. **Marimo 识别** — 查询 `/api/status`、`/api/health` 和 `/`,从响应内容和头部中查找 Marimo 标识 2. **版本提取** — 从 API 响应、服务器头部和 HTML 内容中解析版本信息 3. **WebSocket 握手测试** — 向 `/terminal/ws` 发送安全的 HTTP Upgrade 请求(不通过连接传输任何数据) 4. **差异身份验证检查** — 比较 `/terminal/ws`(应需要身份验证)与 `/ws`(需要身份验证)的行为差异,以确认不一致 5. **版本漏洞检查** — 将检测到的版本与易受攻击范围(<= 0.20.4)和已修复版本(>= 0.23.0)进行比较 **不会在目标系统上执行任何命令。** 仅测试 WebSocket 握手,不通过连接传输任何数据。该检查完全被动且对生产环境安全。 **用法:** ``` # 安装依赖 pip install -r requirements.txt # 单目标(Marimo 默认端口:2718) python CVE-2026-39987_Marimo_RCE_detector.py -t http://marimo-host:2718 # HTTPS 目标 python CVE-2026-39987_Marimo_RCE_detector.py -t https://marimo-host:443 # 从文件批量扫描并输出详细信息 python CVE-2026-39987_Marimo_RCE_detector.py -f targets.txt -o results.json -v # 增加超时以适应慢速网络 python CVE-2026-39987_Marimo_RCE_detector.py -t http://10.0.0.5:2718 --timeout 15 ``` **选项:** | Flag | Description | Default | |------|-------------|---------| | `-t`, `--target` | 单个目标 URL(例如 `http://host:2718`) | — | | `-f`, `--file` | 包含目标 URL 的文件,每行一个(支持 `#` 注释) | — | | `-o`, `--output` | 将结果保存为 JSON 文件 | — | | `--timeout` | 连接超时(秒) | `10` | | `--verify-ssl` | 启用 SSL 证书验证 | 禁用 | | `-v`, `--verbose` | 详细输出完整细节 | 关闭 | **示例输出:** ``` [*] CVE-2026-39987 Marimo Pre-Auth RCE Scanner [*] Scanning 1 target(s)... [*] NOTE: This scanner only checks for endpoint exposure. [*] No commands are executed on target systems. ====================================================================== Target: http://10.0.0.5:2718 Scan Time: 2026-04-14T16:00:00Z Risk Level: CRITICAL ====================================================================== Is Marimo: YES Marimo Version: 0.19.2 /terminal/ws Open: YES — UNAUTHENTICATED Vulnerable: YES *** CRITICAL: Pre-authenticated RCE is possible! *** *** An attacker can get a full PTY shell without any auth *** Details: - Marimo instance detected via /api/status - Marimo version: 0.19.2 - WebSocket upgrade accepted — /terminal/ws accessible WITHOUT auth - CONFIRMED: /terminal/ws accepts unauthenticated connections while /ws requires auth — classic CVE-2026-39987 signature - Version 0.19.2 <= 0.20.4 — VULNERABLE to pre-auth RCE ====================================================================== [*] Scan Complete: 1 targets scanned [*] Marimo Instances: 1 | Vulnerable: 1 | Critical: 1 ====================================================================== ``` ### Nmap NSE 脚本 ``` # 安装 NSE 脚本 sudo cp CVE-2026-39987_Marimo_RCE.nse /usr/share/nmap/scripts/ sudo nmap --script-updatedb # 基本扫描(Marimo 默认端口:2718) nmap -p 2718 --script CVE-2026-39987_Marimo_RCE # 扫描 Marimo 可能运行的常用端口 nmap -p 2718,8080,8443,443 --script CVE-2026-39987_Marimo_RCE # 子网扫描 nmap -p 2718 --script CVE-2026-39987_Marimo_RCE 10.0.0.0/24 # 从文件扫描目标 nmap -p 2718 --script CVE-2026-39987_Marimo_RCE -iL targets.txt # 启用服务版本检测 nmap -sV -p 2718 --script CVE-2026-39987_Marimo_RCE ``` **示例 Nmap 输出:** ``` PORT STATE SERVICE 2718/tcp open http | CVE-2026-39987_Marimo_RCE: | VULNERABLE: | Marimo Pre-Auth RCE (CVE-2026-39987) | State: VULNERABLE | Risk level: CRITICAL | Marimo Version: 0.19.2 | /terminal/ws: accessible without authentication | Description: | The Marimo /terminal/ws WebSocket endpoint accepts connections | without authentication, enabling pre-authenticated RCE. | An attacker can obtain a full PTY shell without any credentials. | References: |_ https://nvd.nist.gov/vuln/detail/CVE-2026-39987 ``` ### 手动验证 如果可以访问 Marimo 实例: ``` # 通过 API 检查 Marimo 版本 curl -s http://:2718/api/status | python3 -m json.tool # 测试 /terminal/ws 的 WebSocket 升级(应在无认证时**不成功**) curl -s -o /dev/null -w "%{http_code}" \ -H "Upgrade: websocket" \ -H "Connection: Upgrade" \ -H "Sec-WebSocket-Key: dGVzdC1rZXktMTIzNDU2Nzg=" \ -H "Sec-WebSocket-Version: 13" \ http://:2718/terminal/ws # 如果返回 101(Switching Protocols),则端点在无认证下开放 # 如果返回 401/403,则已强制执行认证(已修复或加固) # 作为对比,测试 /ws(应始终要求认证) curl -s -o /dev/null -w "%{http_code}" \ -H "Upgrade: websocket" \ -H "Connection: Upgrade" \ -H "Sec-WebSocket-Key: dGVzdC1rZXktMTIzNDU2Nzg=" \ -H "Sec-WebSocket-Version: 13" \ http://:2718/ws ``` 如果 `/terminal/ws` 返回 101 而 `/ws` 返回 401/403,则这是经典的 CVE-2026-39987 特征签名。 ## 妥协指标 在环境中留意以下迹象: | Indicator | Where to Check | What to Look For | |:---|:---|:---| | Unauthorized WebSocket connections | Server/proxy logs | 来自意外 IP 的 `/terminal/ws` 连接 | | PTY session creation | Process monitoring | 由 Marimo 服务器生成的意外 Shell 进程 | | File access | File audit logs | 对 `.env`、凭据文件或 SSH 密钥的读取 | | Credential usage | Cloud provider audit logs | 使用存储在 Marimo 环境中的密钥进行的 API 调用 | | Outbound data transfer | Network monitoring | 来自 Marimo 主机的异常外发流量 | **调查命令:** ``` # 检查活动的 WebSocket 连接 ss -tnp | grep # 审查进程树是否存在异常 Shell ps aux --forest | grep -A5 marimo # 检查 .env 或凭证文件是否被近期访问 stat .env stat ~/.aws/credentials # 审查云提供商活动日志是否存在未授权访问 aws cloudtrail lookup-events --lookup-attributes AttributeKey=AccessKeyId,AttributeValue= # 检查是否存在未授权的出站连接 netstat -tnp | grep ESTABLISHED | grep -v 127.0.0.1 ``` ## 修复 **立即操作(现在就做):** 1. **升级到 Marimo 0.23.0 或更高版本**(`pip install --upgrade marimo`) 2. **限制 Marimo 实例的网络访问**(通过防火墙规则仅绑定到 localhost 或受信任 IP) 3. **检查未授权的连接** 在服务器日志中 **短期(本周内):** 4. **轮换所有凭据**(AWS 密钥、API 令牌、数据库密码、云服务账户),这些凭据可能被 Marimo 环境访问 5. **审计云提供商活动日志**,查找使用可能已泄露凭据进行的未授权 API 调用 6. **检查 `.env` 文件和环境变量**,查找可能已暴露的敏感数据 7. **检查持久化机制**(未授权的 SSH 密钥、cron 作业、修改的启动脚本) **长期:** 8. **不要直接将笔记本环境暴露到互联网**(使用 VPN 或 SSH 隧道) 9. **将 AI/ML 开发环境视为高安全资产**(它们包含云凭据并具备代码执行能力) 10. **将笔记本服务器纳入定期漏洞扫描计划** 11. **实施网络监控**,对笔记本服务器实例设置异常连接告警 ## 参考 - [The Hacker News — Marimo RCE Flaw CVE-2026-39987 Exploited Within 10 Hours](https://thehackernews.com/2026/04/marimo-rce-flaw-cve-2026-39987.html) - [SecurityWeek — Critical Marimo Flaw Exploited Hours After Public Disclosure](https://www.securityweek.com/critical-marimo-flaw-exploited-hours-after-public-disclosure/) - [BleepingComputer — Critical Marimo Pre-Auth RCE Flaw Now Under Active Exploitation](https://www.bleepingcomputer.com/news/security/critical-marimo-pre-auth-rce-flaw-now-under-active-exploitation/) - [Security Affairs — CVE-2026-39987: Marimo RCE Exploited in Hours After Disclosure](https://securityaffairs.com/190623/hacking/cve-2026-39987-marimo-rce-exploited-in-hours-after-disclosure.html) - [CSA Labs — Marimo Pre-Auth RCE: AI Development Toolchain Under Attack](https://labs.cloudsecurityalliance.org/research/csa-research-note-marimo-rce-cve-2026-39987-ai-toolchain-202/) - [GBHackers — Marimo RCE Vulnerability Exploited Within 10 Hours](https://gbhackers.com/marimo-rce-vulnerability-exploited/) - [InfoWorld — Critical Flaw in Marimo Python Notebook Exploited Within 10 Hours](https://www.infoworld.com/article/4157823/critical-flaw-in-marimo-python-notebook-exploited-within-10-hours-of-disclosure-2.html) ## 作者 **Kerem Oruç** — Cybersecurity Engineer - GitHub: [@keraattin](https://github.com/keraattin) - Twitter: [@keraattin](https://twitter.com/keraattin)
标签:0day, AI/ML, AI工具链攻击, AWS凭证窃取, CVE, CVSS 9.3, CWE-306, Marimo, Nmap, NSE, PTY Shell, Python Notebook, Python扫描器, RCE, /terminal/ws, Websocket, 修复版本0.23.0, 在野利用, 安全, 快速披露, 数字签名, 数据科学, 未授权访问, 检测脚本, 漏洞, 编程工具, 网络安全, 虚拟驱动器, 资源验证, 超时处理, 远程代码执行, 逆向工具, 隐私保护, 预认证