多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

rust-review 对抗性 Trait 实现审计指南:如何发现 `unsafe` 代码信任用户 Trait 返回值导致的越界写漏洞(TRAITADV)

rust-review 对抗性 Trait 实现审计指南:如何发现 `unsafe` 代码信任用户 Trait 返回值导致的越界写漏洞(TRAITADV) AI 技能AI 插件应用安全网络安全AI 评测【免费下载链接】skillsTrail of Bits Claude Code skills for security research, vulnerability detection, and audit workflows项目地址https://gitcode.com/gh_mirrors/skills8/skills点击查看免费下载导读本文讲解 Trail of Bitsskills8仓库中rust-review插件的adversarial-trait-finder检测器Finding ID 前缀TRAITADV当 Rust 库公开一个以 trait 为泛型边界的 API并在unsafe操作中信任 trait 方法如Read::read、Iterator::next、Hasher、ExactSizeIterator::len返回的“长度/数量/索引/哈希”时恶意实现方如何把这种信任变成堆越界写OOB write。读完本文你将掌握该漏洞的完整 bug shape、三条判定 Gates、两类误报排除规则以及把 trait 输出视为不可信输入的标准修补方案同时会看到这一 bug class 在rust-review编排管线中的实际接入方式manifest 声明、has_unsafe门控、worker 执行与发现文件格式。漏洞形态Bug Shape库信任 trait 返回值unsafe越界写adversarial-trait-finder的核心研究模型非常具体Bug shape研究库接受T: Read基于T::read()报告的字节数分配缓冲区并通过未检查的unsafe写操作写入。敌对的impl Read for HostileType返回一个大于实际缓冲区的尺寸 → 越界写OOB write。这与经典 Rust 安全审计中的“调用者即敌人”视角一脉相承一旦一个 generic API 暴露给外部T的具体实现就不受库作者控制。凡是把 trait 方法输出当作权威事实、再喂给unsafe长度信任汇点length-trusting sink的代码都可能被一个合法但恶意的impl攻破。在rust-review的编排体系中这一 bug class 位于logic-correctness集群编号为adversarial-trait前缀TRAITADV。见 prompts/clusters/manifest.json 中logic-correctness集群的 passes 列表{ bug_class: adversarial-trait, prefix: TRAITADV, prompt: prompts/general/adversarial-trait-finder.md, requires: [has_unsafe] }requires: [has_unsafe]意味着该 pass 仅在目标代码库包含unsafe由 Phase 1 的能力探测决定时才会被计划选中——因为这里的可利用后果正是unsafe代码中的内存破坏纯 safe-Rust crate 不存在该 sink。plugins/rust-review/README.md 中也将“hostile generic trait impls”列为logic-correctness集群覆盖的逻辑正确性问题之一并明确“The hostile-trait (TRAITADV) and closure-panic (CLOSUREPANIC) passes requirehas_unsafe”。Gates三条判定标准缺一不可adversarial-trait-finder定义了三个必须同时满足的门槛Gates用于把真实的 TRAITADV 从“泛型库常见写法”中筛出来。Gate 1公开的泛型 API trait 边界参数代码必须是一个公开的public泛型 API其参数带 trait 边界例如T: Read、T: Iterator、T: Hasher、T: ExactSizeIterator或自定义 trait。对应到集群探测层面prompts/clusters/logic-correctness.md 的 Phase A 提供了如下的rg种子供 worker 先建立库存再逐项审查rg seed: \s*\w\s*:\s*[A-Z] # generic trait boundsrust-reviewworker 在执行这些种子搜索时要求使用rgripgrep 语法\s/\d/\b若rg不可用则必须用 POSIX 类回退\s→[[:space:]]、\d→[[:digit:]]、去掉\b详见 agents/rust-review-worker.md 的搜索纪律。Gate 2trait 方法返回值流入 unsafe 或长度信任汇点实现必须把 trait 方法的返回值尺寸、数量、索引、哈希喂进以下任一unsafe操作或长度信任汇点Vec::set_len—— 直接声明缓冲区长度为“敌报值”get_unchecked/get_unchecked_mut—— 用敌报索引越界访问ptr::write/copy_nonoverlapping在计算偏移处写入 —— 经典 OOB 写路径from_raw_parts—— 用敌报长度构造切片/裸指针。关键澄清文档明确标注的陷阱Vec::with_capacity/reserve不是OOB 写汇点——它只预留容量len仍为0敌对的尺寸无法借此越界写。但攻击者控制的容量是独立的分配/内存耗尽 DoS应作为单独问题记录而不是当作内存破坏上报。Gate 3缺乏防御性校验没有防御性检查确保报告值与实际一致。文档特别强调ExactSizeIterator::len()是提示hint不是保证guarantee——unsafe代码绝不能信任它。同理Read::read返回的“读取字节数”在Read契约中也不是权威保证read本就可以返回比请求更少的字节而一个恶意 impl 甚至可以谎报。只要上游没有对 trait 输出做边界校验Gate 3 即成立。FPs两种明确不算数的情况检测器同时给出了两条“非漏洞”排除规则False Positives供 worker 在核查候选时直接放行Trait 是密封的sealedpub trait T: sealed::Sealed。由于实现被限定在库内部外部无法提供恶意 impl信任假设成立。返回值仅作启发式且下游会校验报告值只用于启发式判断如粗略估算并且在真正进入unsafe汇点之前会被验证。此时信任链被下游校验切断不构成漏洞。这两条 FP 规则与rust-reviewworker 的核查纪律一致先查现有校验与缓解“Check for existing validation or mitigations before reporting”再决定是否上报。Patch把 trait 方法输出当作不可信输入文档给出的修补原则十分简洁Patch将 trait 方法输出视为不可信untrusted对它们做边界约束bound them绝不直接喂给set_len或get_unchecked。具体落地通常包含三件事在进入unsafe前校验用真实可观测信息如已读取字节数、切片真实长度、len cap断言交叉核对 trait 返回值改用安全 API把get_unchecked换成slice::get(..n).ok_or(...)?、把ptr::copy_nonoverlapping换成copy_from_slice让越界变成显式Err而非 UB在// SAFETY:注释中指名上游校验者文档化“谁保证了这个不变量成立”而不是写一句无法验证的“caller ensures len 64”。这与 agents/rust-review-worker.md 中 Finding File Format 的Recommendation字段模板完全同构——worker 上报时需给出可替换的安全代码写法并命名真实的校验来源。在 rust-review 管线中的落地方式触发条件与计划过滤TRAITADV pass 是否进入某次审计由 scripts/build_run_plan.py 的pass_filtered_out()决定。该函数遍历 pass 的requires列表任何一个 capability flag 为假则硬性剔除该 passfor req in requires: if req not in KNOWN_REQUIRES: fail(...) if not flags[req]: return True也就是说has_unsafefalse时 TRAITADV 会在计划阶段被直接丢弃根本不会出现在 worker 的 spawn prompt 中因此 worker 侧不存在“跳过该 pass”的选择——见 worker 协议中Skip subclasses: (none)的说明。执行顺序与冲突消解在 prompts/clusters/logic-correctness.md 中TRAITADV 是 Phase B 的第 2 个 pass。该集群用 Phase A 的一次性种子搜索建立共享库存generic trait bounds、HashMap/HashSet、RefCell等随后各 pass 复用同一库存避免重复扫描。集群还给出了相邻 bug class 的去冲突规则确保同一个根因不被重复贴上多个标签ORDEQHASHvsKEYMUT手写Ord/Hash实现本身破坏契约是ORDEQHASH对一个本已正确的 key 在集合内原地修改才是KEYMUT。CLOSUREPANIC本集群vsPANICUNWINDmemory-safety 集群用户闭包在两个指针操作之间 panic 使unsafe脚手架不一致 →CLOSUREPANIC容器元数据在 unwind 后残留陈旧 →PANICUNWIND。TRAITADV 与ORDEQHASH同属“trait 实现危险”但视角不同前者是恶意实现者主动利用外部impl谎报长度攻击库后者是库自身实现违反契约a b ⟹ hash(a) hash(b)等不变量被破坏导致 HashMap/BTreeMap 崩溃见 prompts/general/ord-eq-hash-finder.md。发现文件与后续判定worker 确认的每个 TRAITADV 发现会以TRAITADV-NNN.md写入$(pwd)/.rust-review-results/iso-timestamp/findings/frontmatter 包含id、bug_class: adversarial-trait、location单条path:line、function、confidence、worker正文按七段结构撰写Description / Code / Data flow / Reachability trace / Impact / Mitigations checked / Recommendation。随后 dedup-judge 按(path, line, bug_class)等 Tier 合并重复项fp-judge 给每个 primary 打fp_verdict与severityseverity_filter只影响最终REPORT.md的渲染不决定 worker 是否上报。完整协议见 agents/rust-review-worker.md 与 skills/rust-review/SKILL.md。实战核查清单可直接复制使用对照 prompts/general/adversarial-trait-finder.md 原文可把审计流程固化为以下清单找边界rg \s*\w\s*:\s*[A-Z]列出所有公开泛型 API 与 trait 边界。找汇点对每个边界候选搜索set_len、get_unchecked、ptr::write、copy_nonoverlapping、from_raw_parts的调用判断其索引/长度来源是否为 trait 方法返回值。找校验确认汇点上游没有把报告值与真实长度交叉核对确认 trait 未密封、返回值不是“仅启发式下游校验”。区分 DoS若攻击面只落在with_capacity/reserve按“分配/内存耗尽 DoS”单独记录不要混入内存破坏类。写修复建议给出带边界约束或安全 API 的替换代码并在// SAFETY:中指名真正的校验方。按此清单审计者可以稳定复现 TRAITADV 的完整判定路径从 generic trait bound 到 unsafe 长度信任汇点再到恶意 impl 的越界写后果。小结adversarial-trait-finderTRAITADV把“公开泛型 API unsafe 长度信任”这一组合精确建模为可利用漏洞T::read()/ExactSizeIterator::len()等 trait 输出只是提示而非保证恶意实现可以谎报尺寸使库在set_len、get_unchecked、copy_nonoverlapping上越界写。三条 Gates泛型公开 API、unsafe 汇点、缺校验与两条 FP 规则密封 trait、下游校验让检测器既能命中真漏洞又不至于把普通泛型库误报成高危其requires: has_unsafe门控、硬过滤式计划选择、七段式 finding 文件与后续 dedup/fp 判定展示了这类“基于研究 bug shape”的检测器在rust-review并行审计管线中从探测到报告的完整落地方式。赞分享AI 技能AI 插件应用安全网络安全AI 评测【免费下载链接】skillsTrail of Bits Claude Code skills for security research, vulnerability detection, and audit workflows项目地址https://gitcode.com/gh_mirrors/skills8/skills点击查看免费下载相关推荐Rufus U盘启动盘制作工具5 分钟做出 Windows 11 安装盘Rufus U盘启动盘制作工具5 分钟做出 Windows 11 安装盘 系统崩了要重装手里的 U 盘却只是普通存储盘根本开不了机。Rufus 是一款免费桌面应用开发工具Rust By Example 深度解析使用 dyn 返回 Trait 对象动态分发入门Rust By Example 深度解析使用 dyn 返回 Trait 对象动态分发入门 Rust 编译器在编译期必须知道每个函数的返回类型占用多少内存文档教程LobeHub deep-review 对抗式验证子代理逐条证伪代码审查发现的设计与实现LobeHub deep review 对抗式验证子代理逐条证伪代码审查发现的设计与实现 本文以 LobeHub 仓库中 deep review 技能的核心模人工智能AI 应用大模型AI Agent多智能体工具调用前端后端上一篇XNBCLI终极指南让星露谷物语模组开发变得像搭积木一样简单下一篇百度网盘解析工具三步获取真实下载地址的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表