ShovalBenjer/protobuf-fuzz-guard

GitHub: ShovalBenjer/protobuf-fuzz-guard

一款 Protobuf schema 安全扫描与多语言 fuzz harness 自动生成工具,能在开发阶段检测递归和嵌套类漏洞模式并支持 CI 门禁集成。

Stars: 1 | Forks: 0

# protobuf-fuzz-guard 在攻击者之前发现 protobuf schema 漏洞,并通过一条命令将每个 message 转化为跨四种语言的持续 fuzz 活动。 ``` × Recursive message reference: Tree.left references itself. Vulnerable to │ unbounded recursion attacks. ╭─[service.proto:5:5] 4 │ string value = 1; 5 │ Tree left = 2; · ───────┬────── · ╰── here 6 │ Tree right = 3; ╰──── help: Unbounded stack recursion via deeply nested messages ``` ## 为什么这很重要 Protobuf 解析器在所有语言中都存在相同的漏洞类别。 此工具会根据主要安全公告中记录的三种漏洞类别检查您的 schema: | 安全公告 | Runtime | 类别 | 修复版本 | | --- | --- | --- | --- | | CVE-2024-7254 (CVSS 8.7) | protobuf-java, protobuf-kotlin, JRuby | 解析嵌套 group 作为 unknown field 时的 Stack overflow | 3.25.5, 4.27.5, 4.28.2 | | RUSTSEC-2020-0002 (CVE-2020-35858, CVSS 9.8) | Rust prost | 解码深度嵌套输入时的 Stack overflow | prost 0.6.1 | | RUSTSEC-2024-0437 (CVE-2025-53605) | Rust protobuf | `skip_group` 中不受控的递归 | rust-protobuf 3.7.2 | ## 您将获得什么 - 能够指出确切字段和行的源码跨度诊断信息,通过 `miette` 渲染。 - 通过单条命令生成四种语言的 fuzz harness。 - 基于上述三项安全公告的漏洞目录。 - JSON 输出以及在发现严重问题时返回 `1` 的退出代码,从而使 `protofuzz scan` 能够独立作为 CI 的门禁。 - 单个静态二进制文件。无需 runtime,无需网络访问,且依赖树已在 CI 中通过 `cargo-audit` 和 `cargo-deny` 进行审计。 ## 安装 ``` cargo build --release --locked ./target/release/protofuzz --help ``` ## 扫描 schema ``` protofuzz scan path/to/service.proto ``` 诊断信息将输出到 stderr。添加 `--json` 可在 stdout 获取机器可读的检测结果: ``` protofuzz scan --json path/to/service.proto ``` 以此为 pipeline 设置门禁。当存在任何严重检测结果时, 该命令将以 `1` 退出: ``` protofuzz scan proto/**/*.proto ``` ## 生成 harness 一条命令即可将每个 message 的 harness 写入到 `fuzz_harnesses//`。传入 `-l` 来选择语言: ``` protofuzz generate service.proto -l rust -l go -o out/ ``` ## 立即尝试 将以下内容保存为 `tree.proto`: ``` syntax = "proto3"; message Tree { string value = 1; Tree left = 2; Tree right = 3; group Legacy = 4; } ``` 扫描它: ``` protofuzz scan tree.proto ``` 您将获得三个严重检测结果,每一个都会在其源码位置高亮显示: 两个递归引用以及已弃用的 `group` field。退出代码为 `1`。 ## 检测规则 | 规则 | 严重程度 | 模式 | | --- | --- | --- | | Message 嵌套深度达到 5 或以上 | critical | `PROTOBUF-RECURSION-PROTO2` | | Message 嵌套深度在 3 到 4 之间 | warning | none | | 直接递归 message 引用 | critical | `PROTOBUF-RECURSION-PROTO2` | | `group` 或 `TYPE_GROUP` field | critical | `CVE-2024-7254-CLASS` | | 重复的嵌套 message | warning | none | | 三个或更多重复的 `bytes` field | warning | `PROTOBUF-UNKNOWN-FIELD-OVERFLOW` | ## 生成的 Rust harness Rust 目标使用 `prost` 进行解码并执行往返测试。`prost` 默认通过 `DecodeContext` 强制执行 100 的递归限制,因此除非启用了 `no-recursion-limit`,否则该 harness 自带 DoS 保护。 ``` #![no_main] use libfuzzer_sys::fuzz_target; use prost::Message; use acme_v1::Person; fuzz_target!(|data: &[u8]| { if let Ok(msg) = Person::decode(data) { let mut buf = Vec::with_capacity(msg.encoded_len()); msg.encode(&mut buf) .expect("re-encoding a successfully decoded message is infallible"); let _ = Person::decode(buf.as_slice()); } }); ``` ## 开发 ``` cargo fmt --all --check cargo clippy --workspace --all-targets -- -D warnings cargo nextest run --workspace ``` CI 会运行 `rustfmt`、拒绝警告的 `clippy`、`nextest`、`cargo-audit`、 `cargo-deny` 以及 nightly 版本的 fuzz 冒烟测试。Fuzz 相关代码位于 [`fuzz/`](fuzz/README.md) 并且需要 nightly 工具链。供应链策略位于 [`deny.toml`](deny.toml)。 ## 目录结构 ``` crates/pfg-core/ Library: span-aware parser, scanner, harness generator crates/protofuzz-cli/ The protofuzz binary, built on clap fuzz/ cargo-fuzz targets that self-test the scanner docs/ Research report and migration plan legacy/ Original Python implementation, kept for reference ``` ## 许可证 MIT
标签:可视化界面, 通知系统