#15208·rocksdb

【BUG】 RocksDB-v6.26.1 中 BlockPrefixIndex::Builder::Finish 函数中 uint32_t 溢出导致堆缓冲区分配失败和越界写入

作者: wkxNiubi创建于 2026年9月14日更新于 2026年9月14日

问题描述

entry_index 和 num_blocks 分别来自 SST 文件中的 kHashIndexMetadata 区块的字节,采用 5 字节的 varint 格式进行编码,完全由攻击者控制。当 BlockPrefixIndex::Create 读取这两个值时,它只使用前缀区块的大小来验证 prefix_size;由于 pos + prefix_size 采用 64 位操作计算,此检查不会进行循环。entry_index 和 num_blocks 本身没有范围验证。在 Builder::Finish 中,num_blocks_per_bucket[bucket] += current->num_blocks 以 uint32_t 形式累加,如果超过 2^32,则会进行循环;total_block_array_entries 根据循环值计算,因此第 120 行的 new uint32_t[total_block_array_entries] 分配了过小的缓冲区。填充循环中,每个记录都会写入 current->num_blocks 次,写入值是由攻击者选择的递减序列(current->end_block - iter),而 last_block 则从缓冲区的尾部遍历到分配区域的起点。这种不安全的数据流完全基于不可信的 SST 字节,并且将在数据库打开、导入或检查期间执行:index_type=kHashSearch 从文件的属性中解码,rep->table_prefix_extractor 从文件的 prefix_extractor_name 属性中创建,HashIndexReader::Create 直接将这两个由攻击者控制的区块传递给 Create。安全后果是堆内存损坏:打开数据库时几乎肯定会崩溃(DoS),并且会形成由攻击者完全设置的有界但写入值的线性越界写入原语,可以覆盖缓冲区前面的堆内存。

内容来源: facebook/rocksdb