LAVA: Large-scale Automated Vulnerability Addition
本文提出了一种新颖的基于动态污染分析的技术 LAVA,它可以快速、自动地向程序源代码中注入大量实际的错误,从而生成地面真实语料库。形成了一个基础的方法,产生大量真实脆弱性库的需求,为工具开发人员提供了一个高质量的、严格的工具评估方法。
目的
作为一个插入漏洞的工具,帮助检验漏洞检测工具是否有效
其漏洞的特点为:
- 物美价廉
- 跨越程序的执行生命周期
- 嵌入代表性控制和数据流
- 带着一个作为存在证明的输入
- 只有一小部分可能的输入显示
希望使用它来组装大型语料库,用于评估和开发漏洞发现技术和系统。
实现思路
识别执行跟踪位置,其中输入字节相关,不确定控制流,并且没有被修改太多。
在程序中添加代码,使得可控输入能够触发漏洞,lava通过一个程序中运行该程序下的动态污染分析得到一个具体的输入。
污点分析
每个位置标记输入的影响,如果影响为0则是完全输入的拷贝。简单处理和未处理
另外一个基于污染的度量是活性,如果在与决定分支的任何字节相关联的污染标签集中找不到特定的输入字节标签,那么它的活性为0。
通常会选用简单而且低活性的位置,最好是输入的直接副本的位置且完全死亡的来使用。即利用死数据在攻击点注入 bug。
漏洞插入
lava添加了一种确保每个错误只由一个特定输入触发的机制,最好使用各种不同的触发机制注入错误,会更全面的完成工具评估; 逐个比较输入字节将允许 coveragemaximizing fuzzers 通过一次猜测一个字节来增量地发现 bug,而不必一次猜测整个32位触发器。
文中提到,使用不太安全的strcpy和strncpy以及替换memcpy使用的数据的大小都能够生成漏洞,这种漏洞产生方法很简单但是许多这样的转换将严重损害程序的正确性,以至于在每个输入上都会崩溃。
Keromytis (Keromytis et al. Tunable cyber defensive security mechanisms,https://www.sbir.gov/sbirsearch/detail/825791, August 2015 )提出了一个更复杂的方法: 有针对性的符号执行可以用来找到有潜在危险但目前安全的程序路径; 然后可以分析符号路径约束,并用来删除目前防止 bug 的输入检查。 但这使用到符号执行,会导致庞大的计算成本。
LAVA 采用的方法计算成本较低ーー其最昂贵的步骤是动态污染分析,每个输入文件只需进行一次。 每个经过验证的 bug 都保证带有一个触发输入。
原文中在file,bash,readelf和tshark上进行了效果测试
LAVA-1和LAVA-M
LAVA-1这个语料库由69个缓冲区溢出错误组成,这些错误被注入源代码中,每个错误在 git 仓库中的不同分支上,输入的模糊版本经过验证,随代码一起引发崩溃检查。 注入了两种类型的缓冲区溢出,每种类型都使用单个4字节的 DUA 来触发和控制溢出
-
触发器和旋钮
在这种类型的 bug 中,对4个字节,两个为旋钮,2个为触发器,使用 触发器的两个字节对一个魔术字进行比对,以确定是否会发生溢出。 旋钮决定溢出多少。 因此,如果输入中的2字节无符号整数是一个特定的值,但只有当输入中的另外2字节大到足以引起麻烦时,这些错误才会显现出来。
-
范围
如果魔术字只是在某个范围内,这些 bug 就会触发,但是也会使用神奇值来确定溢出的程度。 神奇的值是一个4字节的无符号整数,范围不同
LAVA-M 语料库是8.24版本的源代码的四个副本。 一份拷贝有44个 bug 注入 base64,并且有44个已知的单独触发这些 bug 的输入。 另一个版本在 md5sum 中有57个 bug,第三个版本在 uniq 中有28个 bug。 最后,还有一个副本,其中同时存在2136个 bug,并且可以在 who 中单独表示
测试结果
针对每个程序运行 FUZZER 和 SES,每个程序有5个小时的运行时间。 Md5sum 使用 -c 参数运行,以检查文件中的摘要。 Base64运行 d 参数,解码基数64。
Ses 在 uniq 或 md5sum 中没有发现 bug。 在 uniq 中,我们认为这是因为控制流过于不受约束。 在 md5sum 中,SES 未能执行超过哈希函数第一个实例的任何代码。base64上有效果, 该工具在44个插入的 bug 中找出了9个 base64中的 bug; 这些 bug 包括深度和浅度的 bug,因为 base64是一个分析起来非常简单的程序。 Ses 的结果对于谁来说有点复杂。 它为使用两个 DUAs 中的一个的用户找到所有的 bug,并且所有这些 bug 都在跟踪的早期发生。 我们的方法同时注入多个 bug 的一个缺陷是多个 bug 共享同一个攻击点。 这能否很好地代表真正的 bug 还有待商榷。 实际上,这意味着 SES 只能在每个攻击点发现一个 bug,因为在同一个攻击点发现一个额外的 bug 并不一定需要覆盖新的代码。 Lava 当然可以改变,使每个 bug 都包含新的代码覆盖。 Ses 还可以得到改进,以找到每个攻击点的所有缺陷,这意味着为同一组条件生成多个满意的输入。
Fuzzer 在除了who之外的所有实用程序中都发现了错误。与 SES 不同,这些错误在整个程序中的分布相当均匀,因为它们只依赖于猜测输入文件中正确位置的4字节触发器。 Fuzzer 未能找到令人惊讶的漏洞。 我们推测用于模糊器的种子文件(utmp 文件的前768字节)可能太大,无法通过随机变异进行有效探索,但需要进行更多的调查以确定真正的原因。 事实上,这类工具异常正是人们希望在 LAVA 中发现的类型,因为它们代表了工具可能很容易获得收益的领域。 我们注意到 FUZZER 和 SES 发现的 bug 几乎没有重叠(两个工具都只发现了2个 bug)。 这是一个非常有希望的结果,因为它表明,各种错误创建的lava不是只适合一个特定的错误发现策略。
未来工作
注入其他类型的 bug,例如时间安全 bug (use-after-free)和元字符 bug (例如格式化字符串)。
很可能某些类型的错误是不能通过基于污染的措施注射的。 例如,逻辑错误、加密缺陷和侧通道漏洞,所有这些似乎都在一个相当不同的层次上运行,而这些层次上的数据流触发的漏洞 LAVA 正好位于产生的位置。
LAVA 会引入未初始化的 bug,比如代码中未初始化指针的后用免费和解引用,这些指针会从 DUA 值上吸取信息,以便以后用于触发 bug。 在某些情况下,正在评估的工具甚至发现了这些真正的错误,是由LAVA造成的
在我们对漏洞发现工具的初步评估中,我们只测量了失误率; 没有尝试去测量虚警率。 对于生成触发输入的工具,就像 SES 和 FUZZER 一样,测量虚警率应该是微不足道的。 但在静态分析器和抽象释义分析器上就很重要。