- AI 技能
- AI 插件
- 应用安全
- 网络安全
- AI 评测
【免费下载链接】skills
Trail of Bits Claude Code skills for security research, vulnerability detection, and audit workflows
导读
本篇文章聚焦于 rust-review 插件中一个容易被忽略、却可能导致认证绕过与路径混淆的逻辑缺陷类别——字符串比较缺陷(STRCMP)。它对应仓库中 string-comparison-finder.md 这份 bug-finder 提示词文档,讲解如何识别"用starts_with/ends_with/contains等子串谓词代替全等比较"以及"大小写敏感性混用"这两类安全决策漏洞。读完本文,你将掌握 STRCMP 的缺陷形态(Bug Shape)、判定门槛(Gates)、误报排除规则(FPs)与修复模式(Patch),并理解它在 rust-review 逻辑正确性(logic-correctness)集群中的实际执行机制与验证方法。
STRCMP 是什么:一类被编译器放行的逻辑缺陷
Rust 的借用检查器能证明内存安全,却对"比较谓词用错了"这类纯逻辑问题无能为力。s == t与s.starts_with(t)都合法地通过编译,但语义截然不同。rust-review 将这类缺陷归类为STRCMP(String Comparison),在 manifest.json 中注册为logic-correctness集群的第 5 个 pass,对应的 finder 文件即本篇文章的主体 string-comparison-finder.md。
从仓库结构看,STRCMP 属于always 门控的 bug 类:它不要求代码库存在unsafe、FFI 或并发代码,只要逻辑比较发生就可能在纯 safe Rust 中出现。这正是 rust-review 的逻辑正确性集群一直运行的原因——即使has_unsafe=false,此类缺陷依然存在。
Finding ID 前缀
STRCMP 类发现统一使用STRCMP前缀,产出的 finding 文件遵循 worker 协议规范(见 rust-review-worker.md)命名为STRCMP-001、STRCMP-002等,写入审计输出目录的findings/子目录。
Bug Shape:两种缺陷形态
原文档将 STRCMP 的缺陷形态定义为两种:
形态一:子串/前缀/后缀谓词代替全等比较
一个安全决策(认证检查、allowlist/denylist、host/origin 校验、文件扩展名过滤、路由)本应要求字符串完全相等,却调用了starts_with/ends_with/contains之一。典型的绕过示例:
// 安全缺陷:allowlist 检查本意是只放行 "/admin" if path.starts_with("/admin") { grant_admin_access(); } // 攻击者请求 "/admin-public" 或 "/admin_backdoor" 均可绕过"/admin".starts_with语义下,"/admin-public"也满足匹配,权限检查被静默绕过。这类问题在 Web 框架路由、反向代理路径匹配、静态资源白名单中尤为常见。
形态二:大小写敏感性混用
在同一值类别(host、path、文件扩展名)的等价检查之间,混用了大小写敏感的全等==与大小写不敏感的eq_ignore_ascii_case,导致"路径混淆"(path confusion)。例如一处校验用host == "example.com",另一处用host.eq_ignore_ascii_case("example.com"),攻击者可用EXAMPLE.com或Example.com绕过前一处检查后,又在后一处被放行。
Gates:判定的两道门槛
原文档明确,一个候选点必须同时满足以下两个条件,才构成 STRCMP 发现:
- 比较门控着安全相关决策:认证检查、allowlist/denylist、host/origin 校验、文件扩展名过滤、路由分发等。纯展示或格式化逻辑不在此列。
- 要么在需要精确身份(exact identity)的地方使用了子串/前缀/后缀谓词(
starts_with/ends_with/contains),要么在同一值类别的等价检查中不一致地混用了大小写敏感与不敏感比较。
FPs:误报排除规则
原文档列出三类应判定为误报(False Positive)的情况,worker 在验证候选点时需严格对照:
- 前缀/后缀匹配本身就是预期语义:例如 MIME 类型前缀匹配(
"text/")、路径层级遍历判断("/api/v1/"前缀)。此时子串匹配不是缺陷,而是业务规则。 - 输入在比较前已被规范化为标准形式:如果攻击者可控输入在进入比较之前统一经过
to_lowercase()等归一化,那么后续的大小写混合风险不复存在。 - 比较属于非安全的展示或格式化逻辑:如 UI 文案判断、日志裁剪等,不构成安全门控。
值得注意的是,这些 FP 规则与 finder 的判定流程形成闭环:worker 在 rust-review-worker.md 的"Either way"规则下需要实际验证每个候选点(追踪数据流、检查现有验证),而不是仅凭形状下结论。
Patch:修复模式
原文档给出的修复指引是:
- 身份决策改用全等比较:使用
==或.eq(),而不是starts_with/ends_with/contains。 - 大小写统一归一化:要么统一使用
eq_ignore_ascii_case,要么统一使用.to_lowercase()后比较,并在代码中文档化所选语义,避免同一值类别内口径漂移。
// 修复形态一:精确身份比较 if path == "/admin" { grant_admin_access(); } // 修复形态二:统一大小写口径并文档化 // 语义:host 比较统一使用 ASCII 大小写不敏感匹配 if host.eq_ignore_ascii_case("example.com") { // ... }在 logic-correctness 集群中的执行机制
Phase A 种子搜索
logic-correctness.md 为 STRCMP pass 提供了两组 Phase-A 种子正则,由 worker 通过rg(ripgrep)在审计范围内执行:
rg seed: "\b(starts_with|ends_with|contains)\b" rg seed: "eq_ignore_ascii_case|to_lowercase|to_uppercase|to_ascii_lowercase|to_ascii_uppercase" # case-folding → STRCMP case-mixing第一组捕获子串谓词候选,第二组捕获大小写折叠(case-folding)调用——正是"形态二"的取证入口。之后按 Phase B 的第 5 个 pass 顺序,将 string-comparison-finder.md 的检测与 FP 指引应用到 Phase-A 清单上。
执行纪律
worker 协议(rust-review-worker.md)对 STRCMP 这类非 consolidated pass 的约束值得注意:
sub_prompt_paths由编排器在 plan 阶段预解析并验证存在,worker 逐 passRead对应 finder 文件;- 所有种子必须以 ripgrep 正则语法运行,
rg缺失时退化为grep -E的 POSIX 类写法(\s→[[:space:]],去掉\b),禁止把含\s的模式直接交给不支持 GNU 扩展的grep并信任空结果——那会把未搜索的 pass 记为cleared,造成覆盖门控失败; - 每个 pass 必须产出
filed:或cleared结果并写入覆盖率文件,skipped:不是合法结果。
覆盖门控与测试验证
仓库通过测试对种子模式的可达性做回归锁定。在 test_prompt_regexes.py 中,test_hashmap_inventory_skips_substring_types等用例验证了逻辑正确性集群的种子提取逻辑;而 test_gating.py 的test_unsafe_scaffolding_passes_filtered_without_unsafe验证了logic-correctness集群在has_unsafe=false时仍保留 ORDEQHASH、STRCMP 等非 unsafe 依赖的 pass,仅剔除需要unsafe的 TRAITADV/CLOSUREPANIC——这从测试层面印证了"纯 safe Rust 代码库同样会命中 STRCMP"的设计意图。同时test_full_run_all_flags_end_to_end_snapshot以黄金快照锁定了 23 个 worker 的编排结构,logic-correctness被拆分为-1/-2两个 chunk,STRCMP 在其中稳定执行。
从查找到裁决:STRCMP 发现的后续流水线
worker 写入STRCMP-NNN.mdfinding 文件后,按 SKILL.md 定义的流水线顺序流转:
- dedup-judge:按
(path, line, bug_class)等多级键合并重复发现。因此 worker 写入的location必须是单一路径path:line、function必须是单一函数名,格式错误会导致 STRCMP 发现漏过合并。 - fp+severity-judge(rust-review-fp-judge.md):对每个 primary 给出
fp_verdict(TRUE_POSITIVE/LIKELY_TP/LIKELY_FP/FALSE_POSITIVE/OUT_OF_SCOPE),幸存者再分配severity/attack_vector/exploitability。威胁模型规则在此起决定性作用:REMOTE下仅能通过本地配置触发的比较缺陷判OUT_OF_SCOPE;LOCAL_UNPRIVILEGED下不跨越权限边界的比较问题判LIKELY_FP。严重度评估同样强调相对性——同一路径混淆在REMOTE下可能是 HIGH 的认证绕过,在LOCAL_UNPRIVILEGED下则显著降级。 - 报告产出:
REPORT.md按severity_filter渲染,REPORT.sarif由 generate_sarif.py 幂等生成。
使用前提与边界
本文描述的 STRCMP finder 是 rust-review 插件审计流水线的一部分。完整审计通过/rust-review:rust-review命令触发,需要先收集威胁模型(REMOTE/LOCAL_UNPRIVILEGED/BOTH)、worker 模型与严重度过滤参数,并依赖uv运行 build_run_plan.py 生成执行计划。需要说明的边界(依据 README.md):
- 纯 C/C++ 代码库请改用
c-review; - Solana/NEAR/Ink 智能合约请使用专门的合约扫描技能;
- 密钥内存零化类问题(Zeroize 等)不在 rust-review 覆盖范围,应使用
zeroize-audit技能。
小结
STRCMP 是 Rust 审计中典型的"逻辑正确性"陷阱:编译器不拦截、静态 lint 难覆盖,却可能直接导致认证绕过与路径混淆。围绕 string-comparison-finder.md 这一 finder 文档,你可以完整复现其判定逻辑——先用starts_with/ends_with/contains与大小写折叠种子的两路搜索建立候选清单,再以"安全门控 + 谓词/口径不当"两道门槛过滤,用三类 FP 规则排除噪声,最终以==/.eq()全等比较与统一大小写归一化完成修复。配合 rust-review 的覆盖门控与双 judge 流水线,这一缺陷类别能够在每次审计中被稳定、可复现地识别和裁决。
- AI 技能
- AI 插件
- 应用安全
- 网络安全
- AI 评测
【免费下载链接】skills
Trail of Bits Claude Code skills for security research, vulnerability detection, and audit workflows
相关推荐
Rust 安全审计 finder 实战:pointer-exposure-finder 如何检测泄漏内存地址并识别 ASLR 绕过风险
Rust 安全审计 finder 实战:pointer exposure finder 如何检测泄漏内存地址并识别 ASLR 绕过风险 本文是 Trail of
AI 技能AI 插件应用安全网络安全AI 评测FontForge 中的 Bézier 样条:三次与二次曲线的数学原理与双向转换指南
FontForge 中的 Bézier 样条:三次与二次曲线的数学原理与双向转换指南 Bézier 样条是字体轮廓的基础,PostScript 与 TrueTy
AI 技能AI 插件应用安全网络安全AI 评测Pixiv Fanbox下载器终极方案:3步搞定创作者内容备份
Pixiv Fanbox下载器终极方案:3步搞定创作者内容备份 fanbox dl是一个高效的Pixiv Fanbox内容下载工具,专为技术爱好者和创作者设计,
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考