Rust 使用后释放(UAF)检测实战:基于 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点击查看免费下载导读本文以 Trail of Bitsskills8/skills仓库中rust-review插件的 UAF 检测器文档为主体系统讲解 Rust 代码中“原始指针逃逸隐式 Drop 作用域”这一高发使用后释放Use-After-FreeUAF漏洞形态的成因、四道验证门Verification Gates、常见误报规避策略与可落地的搜索正则并结合仓库的 memory-safety 集群、worker 协议与 SARIF 导出脚本说明该检测器在真实审计流水线中的运行位置与判定规则。读完本文你将掌握一套可直接用于 Rust 安全审计的 UAF 排查清单理解为什么.as_ptr()之后立刻让源对象 Drop 会制造悬垂指针以及如何用源码证据而非直觉判定一个 UAF 候选是否值得上报。UAF 检测器在 rust-review 中的定位use-after-free-finder是rust-review插件的通用检测器finder之一位于 plugins/rust-review/prompts/general/use-after-free-finder.md其 YAML frontmatter 声明如下name: use-after-free-finder description: Detects use-after-free via raw pointers escaping implicit Drop scope in Rust在整条审计流水线中它隶属于memory-safety 集群。查看 plugins/rust-review/prompts/clusters/manifest.json 可知该集群gate为has_unsafe即只有被审计代码库中存在unsafe代码时整个集群含 UAF才会被调度如果目标是纯 safe Rust crate规划器会直接省略整个集群。这背后的依据是 Rust 内存安全漏洞的共性所有内存安全问题都必然源自unsafe代码——安全代码中的借用检查器已经排除了别名与数据竞争而unsafe { }块内的行为不在其管辖范围内。该集群的共享心智模型在 plugins/rust-review/prompts/clusters/memory-safety.md 中被概括为一句审计咒语对于每个 unsafe 块问三个问题——谁拥有这块内存、它何时被 Drop、还有谁在指向它集群 Phase A 要求先构建一次“unsafe 内存映射”mem_map[site] { kind, type, owner_var, lifetime_scope, drop_site }再按固定顺序运行 8 个 finder其中 UAF 排在第四位前三位为 UNINITREAD、SETLEN、INVFREE。每个 finder 的产出是带UAF-前缀编号如UAF-001的 finding 文件最终经 dedup 判官去重、FPseverity 判官定性与定级后汇入REPORT.md与REPORT.sarif。核心漏洞形态11/14 的 UAF 生产事故遵循同一模式检测器文档明确引用了一项实证研究结论作为 bug shape 依据11/14 的生产环境 UAF 漏洞遵循如下模式——一个复杂对象在某个词法作用域lexical scope内被创建随后通过.as_ptr()/.as_mut_ptr()取出原始指针源对象在作用域结束时被隐式 Drop尤其是match分支或if let绑定中的临时值之后该原始指针才被解引用。用最小化的代码形态示意依据上述 bug shape 归纳的典型错误写法// 错误形态源对象是 match 分支里的临时值语句结束后即被 Drop let p match lookup(key) { Some(v) v.as_ptr(), // v 是临时值match 结束后 Drop None std::ptr::null(), }; // p 此刻已是悬垂指针 unsafe { (*p).field 1; } // UAF解引用发生在 Drop 之后// 错误形态if let 绑定 方法链取指针 let buf; if let Some(s) maybe_string() { buf s.as_bytes().as_ptr(); // s 是 if let 绑定块结束时 Drop } // buf 指向的内存已归还 unsafe { process(buf); } // UAF关键洞察在于问题不在“取指针”本身而在“取指针的源对象生命周期与指针使用点之间的错位”。.as_ptr()返回的裸指针不携带任何生命周期信息借用检查器对它的追踪到此为止——后续对裸指针的解引用不再受 Rust 所有权系统的保护。这解释了为什么该 bug shape 中“临时值”temporaries出现频率极高临时值在语句/表达式结束时被立即 Drop是所有作用域中最短的也是最容易被审计者忽略的。四道验证门ALL 必须通过才允许上报检测器规定只有同时满足以下全部四条时一个候选点才可被归档为UAF-xxxfinding任何一条不满足即“do not file”不上报。Gate 1 — 提取Extraction指针来源必须合法原始指针必须来自以下来源之一.as_ptr()/.as_mut_ptr()slice、String、Vec 等容器的方法Box::into_rawtransmute。注意文档给出的搜索正则\b(Box|CString)::into_raw\b|Vec::into_raw_parts|\btransmute\b还覆盖了CString::into_raw与Vec::into_raw_parts但 Gate 1 对这两者的判定规则与.as_ptr()系来源完全不同见 Gate 2 的分支讨论。在 rust-review 的 memory-safety 集群 Phase A 中对应的种子扫描是rg seed: (\.|::)(as_ptr|as_mut_ptr|into_raw|from_raw(_parts)?)\( # method .into_raw() AND assoc-fn Box::from_raw(/Rc::into_raw(/Vec::from_raw_parts(/CString::from_raw(Gate 2 — 终止Termination后备分配确实被释放这一步是 UAF 判定中最需要细分的环节检测器明确区分了两种提取方式的释放语义情形 A.as_ptr()/.as_mut_ptr()/transmute提取释放来自源对象的隐式 Drop——即源对象离开作用域或被重新赋值。这也是最经典的 UAF 形态作用域结束的Drop就是“free”而指针在 free 之后仍被使用。情形 BBox::into_raw/Vec::into_raw_parts提取这类 API消费consume源对象并抑制作用域退出时的隐式 Drop——into_raw本身就是一种显式的“放弃所有权”操作。因此释放必须来自后续某个显式的Box::from_raw/Vec::from_raw_parts/dealloc/ owner-take一个泄漏leak的into_raw指针如果从未被重新接管不算 UAF它只是内存泄漏不是悬垂访问如果该指针被两次重新接管/释放则应归档为DFREEdouble-free而不是 UAF——详见后文 deconfliction 规则。Gate 3 — 解引用Dereference使用必须时序上晚于 Drop原始指针必须被实际解引用读、写、offset偏移、copy_*类内存拷贝且这些操作在时序上严格发生在 Gate 2 的 Drop 之后。仅“提取后未使用”或“使用发生在 Drop 之前”都不构成 UAF——这正是为什么审计时必须手工构建调用时序而不能只看单行代码。Gate 4 — 无缓解Mitigation absenceDrop 没有被中和如果以下任一机制中和了源对象的 Drop则不构成 UAFmem::forget跳过析构ManuallyDrop包装延迟/取消析构Box::leak显式把生命周期延长到static。也就是说只要存在这些“显式放弃 Drop”的痕迹且语义上合理检测器就判定为设计意图而非漏洞。deconflictionUAF 与 DFREE 的边界检测器文档在 Notes 中给出了一个容易混淆的判定优先级与 memory-safety 集群的 deconfliction 规则一致见 plugins/rust-review/prompts/clusters/memory-safety.mdUAFDFREE仅当是单个指针在 free 之后被解引用一次DFREE需要两次不同的 Drop/free 调用。落到into_raw场景的具体推演是into_raw抑制了隐式 Drop因此基于into_raw指针的 UAF 需要一次显式的后续 freefrom_raw/dealloc作为前提如果这个 free 发生了两次根因就从“悬垂指针”变成“双重释放”应归档为DFREE。配套的 double-free-finder 对此有独立判定ptr::read制造位拷贝但不移走源使堆上对象出现两个所有者两个所有者都走出作用域时同一分配被执行两次析构。同理memory-safety 集群还给出INVFREE对未初始化内存赋值触发对垃圾值执行 Drop优先于UAF的规则以及PANICUNWINDunwind 导致容器元数据与实际元素失配优先于DFREE/UAF的规则。审计者在面对跨类别候选时应先对号入座避免把一个根因标注到错误的 bug class。必须规避的常见误报False Positives检测器文档列出了四类高频误报审计时应直接排除指针被提取但let _binding source;延长了源对象的作用域——只要源对象活到指针使用点之后就没有 UAF。这是最常见的“看着像 UAF、其实安全”的代码。源对象是static——没有 Drop分配永不释放不存在悬垂窗口。Pina mut T且生命周期追踪健全——Pin的引用携带真实生命周期借用检查器可以验证。指针来自Box::leak()——这是显式的生命周期延长到static属于有意的“永远活着”不算漏洞Gate 4 的镜像情形。误报规避策略在 rust-review 流水线中是双层的worker 依据检测器文档现场排除即使 worker 误报了后续rust-review-fp-judge见 plugins/rust-review/agents/rust-review-fp-judge.md还会对每个 primary 施加威胁模型感知的二次核验REMOTE/LOCAL_UNPRIVILEGED/BOTH三种攻击者能力模型并裁决TRUE_POSITIVE/LIKELY_TP/LIKELY_FP/FALSE_POSITIVE/OUT_OF_SCOPE五档结论。可落地的搜索正则与两条“反直觉”提示检测器文档提供了五条 ripgrep 正则覆盖提取点、类型转换点与解引用点\.(as_ptr|as_mut_ptr)\( \b(Box|CString)::into_raw\b|Vec::into_raw_parts|\btransmute\b ptr::(read|write|copy(_nonoverlapping)?) \.(offset|add|sub|read|write)\s*\( let\s\w\s*\s*[^;]\.as_ptr\(\)两条容易被审计新手踩坑的提示原文档 Notes 原文要点offset/add/sub/read/write是裸指针的“方法形式”p.add(i)、p.read()并不存在ptr::offset/ptr::add这样的自由函数——因此解引用点的种子应落在方法形式的那一行第 4 条正则而不是ptr::自由函数行第 3 条正则只覆盖ptr::read/ptr::write/ptr::copy_*。into_raw/into_raw_parts/transmute行是 Gate 1 中.as_ptr()系正则抓不到的“提取来源种子”——Box::into_raw这类调用并不出现.as_ptr()字样但同样是合法的指针提取来源必须单独扫描。在集群 Phase A 的完整扫描集合中见 memory-safety 集群文档与 UAF 相关的种子还包括方法形式的全套.(add|sub|offset|read|write|copy_to|copy_from|copy_to_nonoverlapping|copy_from_nonoverlapping)(_unaligned|_volatile)?\s*\(以及mem::forget/ManuallyDrop::用于识别 Gate 4 的中和机制。在 rust-review 的执行约定中见 plugins/rust-review/agents/rust-review-worker.md这些种子必须通过rgripgrep执行种子写的是 ripgrep 正则语法\s、\d、\b部分grep -E实现会把\s静默当成字面s返回空结果从而制造“假清场”falsecleared。如果rg不可用便携回退是\s→[[:space:]]、\d→[[:digit:]]、丢弃\b丢弃只会放宽匹配不会漏报。worker 落地coverage gate 与 finding 文件协议检测器文档本身是 worker 的“pass 级提示词”最终落地要经过 worker 协议。根据 rust-review-worker 协议UAF pass 运行完毕后worker 必须将每条确认的 UAF 写入独立文件{output_dir}/findings/UAF-001.mdfrontmatter 至少含idUAF-001格式、bug_classuse-after-free、title、location单个path:line禁用 markdown 链接与绝对路径、function、confidence、worker正文按七段式结构撰写## Description/## Code/## Data flow/## Reachability trace/## Impact/## Mitigations checked/## Recommendation在 coverage gate 文件{output_dir}/coverage/worker-N.md中为 UAF pass 登记结果行如| UAF | use-after-free | filed: UAF-001 |或cleared (...)——cleared必须注明实际执行过的种子skipped:不是合法结果。仓库测试 test_validate_artifacts.py 验证了 coverage 行必须与plan.json中(prefix, bug_class)完全逐字一致例如(UAF, use-after-free, cleared (no raw pointer frees))的形态test_gating.py 则验证规划器确实把 use-after-free-finder.md 渲染进 worker 的sub_prompt_paths。SARIF 侧generate_sarif.py 将use-after-free映射为规则描述 “Use-after-free via dangled raw pointer”。修复建议三条出路检测器文档给出了三类修复建议审计报告中的## Recommendation段应结合现场情况择优给出把源对象绑定到更长生命周期的变量——例如let cs CString::new(s)?; ffi(cs.as_ptr());让源对象活到所有指针使用点之后。这条对.as_ptr()系 UAF 最直接有效。确实有意为之则显式化——使用Box::leak或mem::forget并配以说明性注释把“隐式的危险”变成“显式的设计决策”。用引用替代裸指针——换成T让借用检查器重新接管生命周期验证从类型层面消灭该类漏洞。适用前提与限制需要说明的是本检测器只覆盖Rust unsafe 上下文中的悬垂裸指针。它的运行前提是被审计代码库has_unsafetrue纯 safe Rust crate 不会触发 memory-safety 集群。与它相邻但职责不同的检测器还包括cstring-dangling-finderCString::as_ptr()临时值逃逸语句作用域后被 FFI 使用前缀CSTRDANGLE见 cstring-dangling-finder.md、double-free-finderptr::read双重析构前缀DFREE、destructor-skip-findermem::forget跳过安全相关析构前缀DROPSKIP。审计者应结合这些相邻检测器交叉核对避免把 UAF 与 DFREE、DROPSKIP 混淆。整个 rust-review 流水线的调用方式与输出目录约定$(pwd)/.rust-review-results/iso-timestamp/可参考 plugins/rust-review/README.md 与 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点击查看免费下载相关推荐rust-review 插件 PATHJOIN 路径穿越检测器Path::join / PathBuf::push 越界逃逸的审计实战指南rust review 插件 PATHJOIN 路径穿越检测器Path::join / PathBuf::push 越界逃逸的审计实战指南 导读 本指南深入解AI 技能AI 插件应用安全网络安全AI 评测docker-py Configs 指南使用 Python 管理 Docker Swarm 配置对象docker py Configs 指南使用 Python 管理 Docker Swarm 配置对象 导读 docker py 的 client.configAI 技能AI 插件应用安全网络安全AI 评测Rust 指针地址泄露检测实战rust-review 插件的 info-disclosure 集群与 PTREXPOSE 审计Rust 指针地址泄露检测实战rust review 插件的 info disclosure 集群与 PTREXPOSE 审计 本篇技术指南以 Trail oAI 技能AI 插件应用安全网络安全AI 评测上一篇【亲测免费】 ModelViewer3D 项目常见问题解决方案下一篇Qwen2.5-0.5B-Instruct性能测试CPU环境下如何优化推理速度实测数据分享创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考