2021 年,Alexander Kuzmenkov 分享了一些关于 ClickHouse 数据库模糊测试的工作,以及 ClickHouse 的核心工程团队和众多贡献者如何持续改进测试覆盖率。正如 Alexander 所说,“测试是软件开发中的一个主要问题:永远都不够”。
模糊测试一直是 ClickHouse 的重要组成部分。在 Alexander 发布博客文章的同一年,我们的创始人 Alexey 也在西伯利亚 C++ 用户组发表了演讲,介绍了 ClickHouse 团队用于查找 bug 的各种模糊测试方法(视频 & 幻灯片)。该演示涵盖了许多主题,从简单的模糊测试技术到使用 libfuzzer 和 AST Fuzzer 方法的更复杂的技术。
除了上述工作外,我们还积极与其他安全团队、研究人员和合作伙伴合作,对 ClickHouse 数据库进行模糊测试。在这篇博文中,我们将讨论我们最近与WINGFUZZ 团队合作的经历。通过这种合作以及该团队构建的创新模糊测试技术,我们能够发现 ClickHouse 中的一些新问题和有趣的边缘情况。
WINGFUZZ 技术内部
为了了解其工作原理,让我们看看 WINGFUZZ 模糊测试引擎的内部结构,正如其团队所解释的那样。
WINGFUZZ 数据库模糊测试引擎可以帮助生成具有丰富类型的语义正确的 SQL 序列。它主要利用两种优化技术:基于元数据的无语法变异和基于类型亲和性的序列生成。
基本上,每个 DBMS 都有其自身独特的特性和 SQL 方言,包括 ClickHouse。WINGFUZZ 不会依赖语法,而是将数据库的状态总结成一个元数据图,这是一种轻量级的数据结构,可以提高模糊测试中的变异正确性。
具体来说,它首先跟踪内置 SQL 测试用例中语句的元数据,并在执行这些语句时迭代地构建元数据图以描述元数据和语句之间的依赖关系。基于元数据图,它通过随机重新排列现有语句来生成具有新序列的测试用例,并进行元数据引导的替换以纠正重新排列后出现的语义错误。
无语法模糊测试的技术细节可以在“Griffin:无语法 DBMS 模糊测试”研究论文中找到。
为了探索更大的输入空间,WINGFUZZ 可以生成比其他模糊测试工具更多的类型的 SQL 序列。序列生成的核心理念是类型亲和性,它表示 SQL 类型对的有意义的出现(例如,INSERT 和 SELECT)。
在每次模糊测试迭代中,WINGFUZZ 首先主动探索由面向序列的变异生成的 SQL 语句,并使用覆盖反馈分析亲和性。面向序列的变异包括替换、插入和删除,如下所示。如果变异的种子覆盖了 DBMS 中的新代码区域,则将记录由类型更改引起的类型亲和性。
接下来,当记录新的类型亲和性时,WINGFUZZ 逐步生成包含类型对的新 SQL 类型序列,并将它们实例化为实际的 SQL 测试用例。下图显示了 WINGFUZZ 如何找到一个有意义的 SQL 序列,该序列由 CREATE、INSERT、CREATE TRIGGER、INSERT 和 SELECT 组成。
面向序列的模糊测试的更多技术细节可以在“面向序列的 DBMS 模糊测试”研究论文中找到。
问题与修复
由于我们在广泛的测试文件夹中随时可以使用如此多的测试查询,WINGFUZZ 团队能够快速适应其独特的方法并开始对 ClickHouse 进行模糊测试。
虽然在过去几个月里 WINGFUZZ 团队报告了其他一些 bug,但该团队最近进行了一些调整并报告了另外 8 个独特的发现。我们的核心工程团队在这些发现作为 GitHub 问题出现后立即进行了处理(如下面的屏幕截图所示)。
有趣的是,其中一些发现,例如此问题,是在四个月前才引入的。这表明,随着 ClickHouse 开发速度的加快,模糊测试在确保我们产品稳定性和安全性方面发挥着至关重要的作用,因为我们不断前进并构建新功能。
接下来是什么?
这篇博文的主要内容是改进每种数据库技术的模糊测试技术的重要性。模糊测试越多,覆盖范围越广,效果越好。在 ClickHouse,我们认识到这一点,并随着我们扩展功能集,持续将额外的模糊测试工具集成到我们的日常开发流程中。这种主动方法确保每个版本的 ClickHouse 都能以最大的安全性和可靠性交付。
与之前的模糊测试工作类似,我们的团队并没有止步于这些最初的发现。与 WINGFUZZ 团队和 ClickHouse 的工程团队合作,我们的安全团队正在努力将 WINGFUZZ 模糊测试引擎集成到我们的日常测试中。这将在本系列博客文章的下一部分中进行介绍。
最后,我想分享我们创始人 Alexey 对 WINGFUZZ 团队的一段话。这段话是对所有模糊测试爱好者提出的公开挑战!