公开案例复盘
这一章只使用公开来源中的已披露信息。目标不是复现攻击,而是把公开案例改写成 ToLO 学习材料:
- source 是什么?
- 输出经过哪些转换?
- sink 在哪里?
- 缺少哪类 guard?
- 上游如何修复,修复对应哪类
C_SAFE?
读完一组案例后,你应当能拿到任何一个新公开 LLM 应用 CVE,在 5 分钟内压成上面五段。
这一章给你什么
| 你将能做到 | 用到的内容 |
|---|---|
| 用四列拆解(source/transform/sink/guard)分析公开 CVE | §“案例怎么读” + 各 CVE 页 |
| 区分”NVD 写的 CWE”和”ToLO 视角的 source-anchored 解释” | 各 CVE 页 §“对 ToLO 分类的启发” |
| 看懂上游 fix commit 的语义 — 它属于哪一类 sanitizer? | 各 CVE 页 §“修复方式” |
| 把”产品功能不同但根因相同”的案例放在同一框架里 | §“案例怎么读” |
你需要先知道什么
- 七子类(
ToLO-{Exec, Shell, SQL, Path, SSRF, Deser, Template})— 见 Core Patterns。 - 五类
C_SAFE— 见 Defensive Patterns。 - CVE / GHSA / NVD 各代表什么 — 见 先修知识 §7。
案例怎么读
CVE/GHSA 页面通常按传统 CWE 写,例如 code injection、SQL injection、unsafe deserialization。本站读案例时,不是为了背编号,而是为了把它们重新拆成 ToLO 数据流。
读每个案例前,先准备五个问题:
1. source: 哪个值来自 LLM 或受 LLM 影响?是 S_LLM 哪个子集?2. transform: 它怎么被解析、包装、传递?3. sink: 它最后进入什么危险操作?对应 ToLO 哪个子类?4. guard 缺失: 修复前少了什么类型匹配的 sanitizer?5. 修复语义: 上游加了什么?属于哪一类 C_SAFE?案例页结构
每个案例页都按统一模板:
| 段落 | 内容 |
|---|---|
| frontmatter | case(CVE/项目/版本/公开来源/verification)+ tolo(sink_class/channels/boundaries) |
| 一句话 | 据公开来源,问题是什么 |
| 怎么读这个案例 | 教学切入角度 |
| 影响组件 | 受影响模块、版本范围 |
| ToLO 路径 | source / transform / sink / guard 四列 |
| 教学骨架代码 | 最小可读骨架(不可直接复现) |
| 修复方式 | 上游 commit 的语义解读 — 哪一类 C_SAFE |
| 对 ToLO 分类的启发 | 该案例支持/挑战 taxonomy 哪一类 |
| 学习者要带走什么 | 3 条具体可迁移的认识 |
| 读完检查 | 一道题验证理解 |
| 公开来源 | NVD / GHSA / PR / commit 链接 |
一个读案例模板
读案例时填这张表,不要直接读 advisory 抄答案:
| 问题 | 你的标注 |
|---|---|
| 攻击者通道 | C1 / C2 / C3 / C4 / C5(可多选) |
| Source | S_LLM^direct/framework/parsed/structured/rag |
| Transform | parser、agent action、tool input、wrapper、format string、registry dispatch… |
| Sink | ToLO-* 子类 |
| Missing guard | schema / allowlist / parameterized / safe-codec / capability(哪一类 + 为什么没有) |
| 修复属于 | 移除 sink / 加 guard / 权限收缩 / 显式开关 / 版本升级 |
| 残余风险 | 修复是否依赖调用方配置?例如最小权限数据库账号、显式启用 dangerous request? |
这个模板比阅读 advisory 原文更重要,因为它能把不同案例放在同一套知识框架里。
复盘时重点看什么
- 版本口径:NVD、GHSA、release note 和 commit 可能不一致。冲突时保留差异,标
pending,不强行选择”正确版本”。 - source 证据:公开来源是否明确说明 LLM 生成内容、模型输出、agent action 或 tool argument 参与。否则不能上 ToLO 标签。
- sink 证据:是否能对应到七子类之一,或者确实需要扩展 taxonomy。后者要严谨论证。
- 修复语义:上游是移除 sink、加 allowlist、加 capability、调依赖版本,还是只加 warning?后者风险残留。
- 残余风险:修复是否依赖调用方配置?例如数据库最小权限、显式 enable dangerous request?这些是”建议”,不是”强制”。
推荐阅读顺序
先读三个 ToLO-Exec 案例:
- LLMMathChain(CVE-2023-29374)
- PALChain(CVE-2023-36258)
- numexpr(CVE-2023-39631)
它们能帮助理解**“LLM 生成表达式 / 代码”为什么需要执行边界**。
再读两个数据库类案例:
- Vanna AI(CVE-2024-5826,ToLO-Exec via Plotly)
- GraphCypherQAChain(CVE-2024-8309,ToLO-SQL via Cypher)
它们展示了数据分析、可视化、图数据库问答这类高层功能如何把 LLM 输出送入执行或查询 sink。
读完后回到 Defensive Patterns,对照每个案例的修复是否属于 schema、allowlist、parameterized、safe-codec 或 capability。
当前样本偏向 Exec / SQL 的解释
收录的 5 个案例明显偏向 ToLO-Exec 与 ToLO-SQL。这不表示其他子类不存在,只表示:
- 公开、可核验且适合教学的案例还需要继续补充。
- PoC 容易演示的子类(
Exec直接 RCE)更容易拿到 CVE。 - 静默修复的案例(many
Path、SSRF、Template类问题)经常没有 CVE 编号。
新增 ToLO-Path、ToLO-SSRF、ToLO-Template、ToLO-Deser 案例时,应优先找官方 advisory 或项目 security advisory。
收录边界
不写:
- 未披露漏洞
- 真实服务可复现步骤
- 私有 PoC
- 未经核验的版本范围(标
pending,正文使用”据公开来源”这类限定表述)
写:
- 公开 advisory 已发布的 CVE / GHSA
- 已 merge 的修复 commit 的语义解读
- 教学骨架代码(经简化、无可用 exploit)
- 通用模式归纳
后续候选项目
不等于存在漏洞 —— 只是 LLM 编排生态中值得观察的工程面:
- LangChain / LangChain.js
- LangGraph
- Dify
- Flowise
- Langflow
- AutoGPT / OpenHands
- AnythingLLM
- Vanna / DataLine 类 BI agent
- LlamaIndex
- MCP server 生态(filesystem、github、shell server 等)
agent / workflow / tool calling / RAG / browser automation / code execution / database assistant 功能越多,source-to-sink 路径越复杂,值得审计的面也越多。
读完检查
读完任一案例后,尝试不看原文复述:
- 这个案例为什么不是单纯 prompt injection?
- sink 对应哪个
ToLO-*子类? - 修复是防 source、改 sink、加 sanitizer 中的哪一种?
- 修复在
C_SAFE五类中属于哪一类?
如果都能,你已经掌握 ToLO 案例分析的基本方法。
下一步阅读
- Public CVE Case Studies:案例清单与收录标准。
- 然后按推荐顺序读 5 个 CVE 案例。
- 读完后回 Core ToLO Patterns,检查每个案例是否真的支持当前 taxonomy。