By My

be reading 100%

CVE learn

directory

Directory

CVE is my dream.

早在我上小学时,就觉得 CVE 很帅。步入初中时,在初三那年我拿到了广东电信 IPTV 的通用漏洞。步入社会时,我拿到了 Github 的 Bug bounty。但我始终没有去拿一个 CVE 的编号。因为水是可以水的,但我已经水了 CNVD 和 Hackerone,我希望我的第一个 CVE 编号可以是不那么水的,有一点含金量的。

虽然我并不是 Security 行业或领域的从业人员,只是一个爱好者。但我一直觉得 Security 很帅。同样的,虽然我不是 Design 行业的从业人员,但我觉得可以让自己做出来的 project 会好看,有个性。

我并不是一个专精的人。很多时候我每项感兴趣的领域单拎出来都会被降维打击。虽然我单项领域无法媲美专业的从业者,但我感兴趣的领域都有点建树和作品。将 Security、Design、Animation、Computer 合在一起,与之能媲美的人可能会少那么一点。

而现在,我只有 Design 的代表作,而 Security、Animation、Computer 还没有一个能拿得出手的作品。因此我希望会在未来三年,尽可能的补全这些我感兴趣领域的代表作。可能因为 Work 比较闲的缘故,我的时间总会多那么一点来放到我感兴趣的领域上。即使达不到也没有关系,至少也是努力过了,无论如何三年后的自己总会比现在的自己稍微厉害那么一点点。

因此这个页面会记录一些我感兴趣的 CVE 和 CWE 的编号来让我学习,可能会获取到一些新的思路和对某个方面的理解。来帮助我实现这个目标,顺便看看冷门的 CWE 方向,毕竟 OWASP TOP 10 个人没有太大的兴趣。


CVE-2022-36114 1

不受控制的资源消耗

利用 Cargo 的 build script 在构建阶段编译第三方的非 Rust code,同时结合 procedural macros,在执行 cargo run 的过程中触发了一个 Zip Bomb 行为。

对于这个问题的修复,rust-lang 已经给出了一个 补丁修复 Zip_bomb 的问题:

// 在解压 .crate 文件(tar.gz)时,限制最多只能解压出 512MB 的内容。
+const MAX_UNPACK_SIZE: u64 = 512 * 1024 * 1024;

同时引入了 LimitErrorReader: 超过就抛出错误,避免资源被耗尽(比如磁盘写爆)。除此之外并没有对 macros、build 加以限制,只是建议尽可能的用 crates 上提交的 crate。


CVE-2023-40030 1

{OWASP TOP TEN}: 不恰当的网页生成输入中和 XSS

看到这篇通告的时候,我就回想起为什么我看 cargo build --timings 的时候肿么没想到会有 CWE-79。--timings 是一个生成 build 时间的 html 报告。

可以通过在 Cargo.toml 中加入 features = ["<img src='' onerror=alert(0)"] 来触发一个 CWE-79, 因此对这个问题的修复就是,将之前的 Warning, 换成了 bail! 机制。

bail! 宏来自 anyhow 用于方便地提前返回错误。

可以看一下 fix pr,非常有意思,比如 validate_feature_name 函数。

原来:遇到非法 feature name,只输出 warning,流程继续。

if let Some(ch) = chars.next() {Add commentMore actions
        if !(unicode_xid::UnicodeXID::is_xid_start(ch) || ch == '_' || ch.is_digit(10)) {
            config.shell().warn(&format!(
                "invalid character `{}` in feature `{}` in package {}, \
                the first character must be a Unicode XID start character or digit \
                (most letters or `_` or `0` to `9`)\n\
                {}",
                ch, name, pkg_id, FUTURE
            ))?;

        }
    }

我本来想看看 2025-6-27 的 src/cargo/core/summary.rs 这个 fix pr 的区别。但我发现了一个流量密码,那就是 Rc → Arc, 问就是 Thread Safety!

现在:遇到非法 feature name,直接 bail!,构建中止,用户必须修正。

 if let Some(ch) = chars.next() {Add commentMore actions
        if !(unicode_xid::UnicodeXID::is_xid_start(ch) || ch == '_' || ch.is_digit(10)) {
            bail!(
                "invalid character `{}` in feature `{}` in package {}, \
                the first character must be a Unicode XID start character or digit \
                (most letters or `_` or `0` to `9`)",
                ch,
                name,
                pkg_id
            );
        }
    }

在单元测试中,来验证 feature name 是否合法,例如只有 is_ok() 是合法的,而 is_err() 是不合法的:

 #[test]Add commentMore actions
    fn valid_feature_names() {
        let loc = CRATES_IO_INDEX.into_url().unwrap();
        let source_id = SourceId::for_registry(&loc).unwrap();
        let pkg_id = PackageId::new("foo", "1.0.0", source_id).unwrap();

        assert!(validate_feature_name(pkg_id, "c++17").is_ok());
        assert!(validate_feature_name(pkg_id, "128bit").is_ok());
        assert!(validate_feature_name(pkg_id, "_foo").is_ok());
        assert!(validate_feature_name(pkg_id, "feat-name").is_ok());
        assert!(validate_feature_name(pkg_id, "feat_name").is_ok());
        assert!(validate_feature_name(pkg_id, "foo.bar").is_ok());

        assert!(validate_feature_name(pkg_id, "+foo").is_err());
        assert!(validate_feature_name(pkg_id, "-foo").is_err());
        assert!(validate_feature_name(pkg_id, ".foo").is_err());
        assert!(validate_feature_name(pkg_id, "foo:bar").is_err());
        assert!(validate_feature_name(pkg_id, "foo?").is_err());
        assert!(validate_feature_name(pkg_id, "?foo").is_err());
        assert!(validate_feature_name(pkg_id, "ⒶⒷⒸ").is_err());
        assert!(validate_feature_name(pkg_id, "a¼").is_err());
    }

CVE-2023-41051 1

越界访问(out-of-bounds): 访问了本不属于该内存区域的数据。

vm-memoryVolatileMemory 实现未对边界进行严格校验,导致有可能读取到非法的内存区域:

  1. VolatileMemory::get_slice: 返回一段“易失性切片”(VolatileSlice),用于后续的底层操作
  2. VolatileMemory::read/write: 直接从这块内存读/写数据,保证每次都实际发生内存访问

VolatileMemory trait 就是定义了一套访问“虚拟机物理内存”或“特殊硬件内存区域”的低层接口,保证每次读写都真实发生,且不被编译器优化。它让不同的底层实现都能用统一的 trait 操作。

但问题来了,这个通告并不涉及 read/write,更多的是 get_slice 方法,例如:

  1. get_atomic_ref
  2. aligned_as_ref
  3. aligned_as_mut
  4. get_ref
  5. get_array_ref

上述方法有个共同点,都是利用 ref 类方法引起的。它们都尝试返回指向底层内存的 Rust 类型引用(如 &T、&[T] 等),而不是直接读写原始字节数据。它们的实现通常会调用 get_slice,假设返回的内存区域长度足够大。

如果自定义实现的 get_slice 返回的切片长度不足,就会导致这些 ref 方法产生越界引用,造成内存安全风险。例如:

  1. 这些方法假设 get_slice 返回的 VolatileSlice 长度是你要求的大小(比如 T 是 u32,就要 4 字节)。
  2. 如果自定义实现的 get_slice 返回的 VolatileSlice 比你要求的短(比如只返回了2字节)
  3. 这些方法还是会照常把这块内存强转成 &T,这时你访问 &T 时就可能会读到超出实际内存范围以外的内容

仔细欣赏 fix pr 你会发现:

这些方法内部,都会调用 get_slice(offset, count) 拿到一块内存切片,然后把它 reinterpret_cast 成你要的类型引用。因此给 get_slice 加上 assert_eq! 就意味着:

“如果你要 8 字节引用,必须实际拿到 8 字节的内存切片,否则直接 panic,不做 unsafe 操作!”


CVE-2023-38497 1

732: 关键资源的权限分配错误
278: 不安全的保留继承权限