/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */
#content_views .toc,
/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */
#content_views.markdown_views > p:empty:has(+ .toc),
#content_views.markdown_views > .toc + p:empty,
/* 富文本旧版目录标记 */
#content_views.htmledit_views #main-toc,
#content_views.htmledit_views #hr-toc,
#content_views.htmledit_views p[id*=\”-toc\”] {
display: none !important;
}
/* 目录去掉后,紧跟的首个标题不再多出一块上边距 */
#content_views.markdown_views > .toc + h1,
#content_views.markdown_views > .toc + h2,
#content_views.markdown_views > .toc + h3,
#content_views.markdown_views > .toc + h4,
#content_views.markdown_views > .toc + p:empty + h1,
#content_views.markdown_views > .toc + p:empty + h2,
#content_views.markdown_views > .toc + p:empty + h3,
#content_views.markdown_views > .toc + p:empty + h4 {
margin-top: 0 !important;
}
一、漏洞定性
Langflow 是一款用于构建和部署 AI Agent 与工作流的开源平台。其 MCP(Model Context Protocol)服务器的 Stdio 传输方式允许用户注册自定义命令,但该命令被未经任何校验、白名单或沙箱隔离直接传递给 bash -c "exec {command}"。任何已认证用户——包括非管理员账号——在添加恶意 MCP 服务器后,只要 Langflow 拉取服务器列表,命令即被执行。
| 漏洞类型 | OS 命令注入(CWE-78) |
| CVSS 3.1 | 9.9 Critical(AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H) |
| 影响版本 | Langflow < 1.9.0(完整修复需 < 1.10.3) |
| 修复版本 | 1.9.0(API 层白名单);1.10.3(执行层完整加固) |
| 认证要求 | 需要已认证用户(但 LANGFLOW_AUTO_LOGIN=true 默认开启时,无凭证也能拿 token) |
| 在野利用 | 已确认。Previdian 蜜罐自 2026-09-19 起捕获 1,423 次利用尝试,涉及 27 个 IP |
你提供的 Nuclei 模板在逻辑上是正确的,但有一处关键细节需要修正:模板中写的是“升级到 1.9.0”,而 1.9.0 只修复了 REST API 入口的注入路径。如果恶意配置通过 flow 中的 MCP Tools 组件或 tweak 嵌入,1.9.0 至 1.10.2 仍然可被利用。真正的完整修复版本是 1.10.3 。
二、漏洞机制:从 REST 到 shell,零校验
2.1 执行路径
Langflow 在 src/lfx/src/lfx/base/mcp/util.py 的 MCPStdioClient._connect_to_server 中构造子进程参数:
server_params = StdioServerParameters(
command="bash",
args=["-c", f"exec {command_str} || echo 'Command failed…' >&2"],
env=env_data,
)
command_str 来自用户提交的 command 字段,没有任何过滤。bash -c 的 exec 直接执行拼接后的字符串,因此攻击者可以注入 ;、|、$() 等任意 shell 元字符。
2.2 触发时机
命令不需要管理员点击“启动”或“连接”。当 Langflow 获取 MCP 服务器列表(GET /api/v2/mcp/servers?action_count=true)或加载工具时,每个已存储的 stdio 配置都会被尝试启动,命令随之执行 。
2.3 持久化特性
恶意 MCP 服务器配置存储在项目设置中,不在 flow 编辑器中可见。每次服务器列表被加载,命令都会重新执行。这意味着攻击者可以写入一条配置,然后依赖正常的管理操作反复触发,形成持久化后门 。
2.4 env 字段的额外风险
除了 command,env 字段也允许任意环境变量注入。攻击者可以设置 LD_PRELOAD 加载恶意共享库,或覆盖 PATH 使后续命令执行指向攻击者控制的二进制 。
三、1.9.0 修复不完整:1.10.3 才是终点
| < 1.9.0 | 完全脆弱 | REST API 和执行层均无校验 |
| 1.9.0 – 1.10.2 | 部分修复 | PR #12290 在 MCPServerConfig 层加了白名单,阻塞了“Add MCP Server”入口。但执行层仍然使用 bash -c 且无校验,通过 flow 内嵌 MCP Tools 组件或 tweak 传入的配置仍可执行任意命令 |
| 1.10.3+ | 完整修复 | PR #14036 将同一套校验策略应用到执行层,并移除了 bash -c 包装,进程直接 exec,不再经过 shell |
因此,如果你看到“升级到 1.9.0”的建议,那是不完整的。1.9.0 只关闭了最直接的入口。完整的安全版本是 1.10.3 或更高。
四、在野利用态势:真实的、有针对性的
Previdian 的蜜罐数据提供了清晰的利用画像 :
-
时间跨度:2026-09-19 至 10-19,共 1,423 次尝试
-
来源:27 个独立 IP,覆盖比利时、中国、德国、香港、日本、尼日利亚、菲律宾、俄罗斯、塞舌尔、新加坡、韩国、台湾、坦桑尼亚、美国、越南
-
攻击模式:先探测版本 → 尝试 /api/v1/auto_login(蜜罐中返回 403)→ 用常见用户名/密码成功认证 → 立即用 bearer token 访问 MCP 服务器配置端点
-
捕获的载荷:
-
提取 LANGFLOW_SECRET_KEY、LANGFLOW_SUPERUSER_PASSWORD 并外传至 146.70.211[.]112:18764
-
Docker 命令读取宿主机 /etc/passwd
-
id、whoami 等命令执行探测
-
其中一个 IP(192.255.229[.]92)同时被观测到利用 Flowise(CVE-2026-69255)和其他 Langflow 漏洞(CVE-2026-55255、CVE-2026-9198、CVE-2026-0768),说明存在系统性的、针对 AI 基础设施的扫描活动 。
五、Python 检测脚本(安全版)
以下脚本仅做版本指纹与认证端点探测,不发送任何命令注入载荷。适合资产排查。
#!/usr/bin/env python3
"""
CVE-2026-105740 Langflow 安全检测(无注入载荷)
用法: python cve_2026_105740_check.py https://target:7860
"""
import sys
import re
import requests
import urllib3
urllib3.disable_warnings()
TIMEOUT = 10
def check(base):
base = base.rstrip("/")
headers = {"User-Agent": "Mozilla/5.0 (security-check)"}
# 1) 版本探测:Langflow 通常在 /health 或根路径暴露版本
version = None
for path in ["/health", "/api/v1/version", "/"]:
try:
r = requests.get(f"{base}{path}", headers=headers,
timeout=TIMEOUT, verify=False)
except requests.RequestException:
continue
m = re.search(r"(\\d+\\.\\d+\\.\\d+)", r.text[:500])
if m:
version = m.group(1)
print(f"[*] 从 {path} 提取到版本线索: {version}")
break
if version:
parts = tuple(int(x) for x in version.split(".")[:3])
if parts < (1, 9, 0):
print(f"[!] 版本 {version} < 1.9.0,完全脆弱")
print("[!] 立即升级至 1.10.3 或更高(1.9.0 修复不完整)")
elif parts < (1, 10, 3):
print(f"[!] 版本 {version} 在 1.9.0–1.10.2 区间,部分修复")
print("[!] REST API 入口已加固,但 flow 内嵌 MCP 配置仍可利用")
print("[!] 需升级至 1.10.3 或更高")
else:
print(f"[+] 版本 {version} >= 1.10.3,已完整修复")
else:
print("[*] 无法自动提取版本,请手动检查")
print("[*] 方法:登录后台 → 设置 → 关于,或查看容器镜像标签")
# 2) 检查 AUTO_LOGIN 是否开启(无需凭证即可获取 token)
try:
r = requests.get(f"{base}/api/v1/auto_login",
headers=headers, timeout=TIMEOUT, verify=False)
if r.status_code == 200 and "access_token" in r.text:
print("[!] AUTO_LOGIN 已开启:无凭证即可获取 token,攻击门槛为零")
print("[!] 设置 LANGFLOW_AUTO_LOGIN=false 并重启")
elif r.status_code == 403:
print("[*] AUTO_LOGIN 已禁用(/api/v1/auto_login 返回 403)")
except requests.RequestException:
pass
# 3) 检查 MCP 服务器端点是否存在(需认证,不发送注入载荷)
try:
r = requests.get(f"{base}/api/v2/mcp/servers",
headers=headers, timeout=TIMEOUT, verify=False)
if r.status_code == 401:
print("[*] MCP 服务器端点存在,需要认证(正常)")
elif r.status_code == 200:
print("[!] MCP 服务器端点返回 200,可能未启用认证,需人工核查")
except requests.RequestException:
pass
if __name__ == "__main__":
if len(sys.argv) != 2:
print(f"用法: {sys.argv[0]} https://target:7860")
sys.exit(1)
check(sys.argv[1])
说明:该脚本不发送任何命令注入载荷。/api/v1/auto_login 的探测本身是只读的——如果它返回 token,说明目标处于零门槛暴露状态;如果返回 403,说明已加固。
六、Nuclei 模板(安全指纹版)
你提供的 Nuclei 模板是** intrusive 的(会执行 python3 -c 发起 OAST 回调),适合授权测试,不适合生产扫描。以下是一个只读版本**,仅做版本与 AUTO_LOGIN 状态检测:
id: CVE-2026-105740-langflow-detect-safe
info:
name: Langflow CVE-2026-105740 – Safe Version & Config Check
author: security-research
severity: critical
description: |
检测 Langflow 版本与 AUTO_LOGIN 配置,不发送 MCP 命令注入载荷。
完整修复版本为 1.10.3(1.9.0 仅修复 REST 入口)。
reference:
– https://github.com/langflow-ai/langflow/security/advisories/GHSA-7w94-79vh-5mr2
– https://github.com/langflow-ai/langflow/pull/12290
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
cvss-score: 9.9
cwe-id: CWE-78
tags: cve,cve2026,langflow,mcp,rce,detect
http:
– method: GET
path:
– "{{BaseURL}}/health"
– "{{BaseURL}}/api/v1/version"
stop-at-first-match: true
matchers:
– type: regex
part: body
name: version
regex:
– '(1\\.[0-9]+\\.[0-9]+)'
extractors:
– type: regex
part: body
name: detected_version
regex:
– '(1\\.[0-9]+\\.[0-9]+)'
group: 1
– method: GET
path:
– "{{BaseURL}}/api/v1/auto_login"
matchers:
– type: word
part: body
words:
– "access_token"
case-insensitive: true
运行方式:
nuclei -t CVE-2026-105740-langflow-detect-safe.yaml -u https://target:7860
关于你提供的原始 Nuclei 模板:它的流程是正确的(登录 → 创建 MCP 服务器 → 触发列表加载 → OAST 回调 → 删除服务器)。但有两个问题需要注意:
它需要有效的 username/password 变量,并且目标必须允许认证。如果 AUTO_LOGIN 开启,可以直接用 /api/v1/auto_login 获取 token,不需要用户名密码。
它会在目标上创建并删除一个 MCP 服务器配置,这本身就是对目标状态的修改。在非授权环境中不应运行。
七、修复与缓解
7.1 升级(唯一根治)
升级至 Langflow 1.10.3 或更高版本。1.9.0 不够——它只关闭了 REST API 入口,flow 内嵌配置仍可利用 。
# pip
pip install –upgrade langflow>=1.10.3
# Docker
docker pull langflowai/langflow:latest
7.2 关键配置加固
| 禁用 AUTO_LOGIN | LANGFLOW_AUTO_LOGIN=false | 消除零凭证攻击路径。这是最关键的单项缓解 |
| 限制 MCP 包执行 | 设置 LANGFLOW_MCP_SERVER_ALLOWED_PACKAGES | 只允许批准的包通过 npx/uvx 执行 |
| 收紧用户权限 | 审查已注册用户,移除不必要账号 | 降低 PR:L 的实际风险 |
| 监控 MCP 端点 | 检查 /api/v2/mcp/servers 的 POST/DELETE 日志 | 发现异常服务器注册 |
7.3 失陷排查
由于利用会在服务器上执行任意命令,排查应覆盖:
# 1) 检查 MCP 服务器配置(Langflow 数据库中)
# 异常条目:command 含 shell 元字符、env 含 LD_PRELOAD 或异常 PATH
# 2) 检查进程与网络连接
ps aux | grep -E "bash -c|exec" | grep -v grep
netstat -tlnp | grep -E "146\\.70|192\\.255" # 已知攻击者 IP 段
# 3) 检查环境变量是否被泄露
# LANGFLOW_SECRET_KEY、LANGFLOW_SUPERUSER_PASSWORD 是否被外传
# 4) 审查访问日志中 /api/v2/mcp/servers 的异常 POST 请求
grep "mcp/servers" /var/log/langflow/access.log | grep "POST"
Previdian 观测到的攻击者使用了常见用户名/密码组合成功认证。检查是否有弱口令账号,以及认证日志中来自异常 IP 的成功登录 。
八、今晚的判断
CVE-2026-105740 的 CVSS 9.9 和“需要认证”这两个事实并存,意味着它的实际风险高度依赖于你的 Langflow 部署状态:
-
如果 LANGFLOW_AUTO_LOGIN=true(默认)且实例暴露于网络 → 今晚必须处理。攻击者不需要任何凭证就能获取 token,蜜罐数据已经证明有人在系统性地扫描和利用。
-
如果 AUTO_LOGIN=false 且只有可信用户 → 风险显著降低,但仍应升级。恶意内部用户或被盗账号仍然可以利用。
-
如果版本在 1.9.0–1.10.2 之间 → 不要以为升级过就安全了。REST 入口关了,但 flow 内嵌配置的路径仍然敞开。需要 1.10.3。
行动顺序:
确认版本:< 1.9.0 是完全脆弱,1.9.0–1.10.2 是部分修复,>= 1.10.3 是完整修复。
确认 LANGFLOW_AUTO_LOGIN:true 是零门槛暴露。
升级到 1.10.3+,设置 AUTO_LOGIN=false。
检查 MCP 服务器配置中是否有非预期的 command 条目。


