LWN: 再次审视 syzbot 报出的问题!

Linux News搬运工

共 5004字,需浏览 11分钟

 · 2021-10-28

关注了就能看到更多这么棒的文章哦~

Scrutinizing bugs found by syzbot

By Jake Edge
October 13, 2021
LSSNA
DeepL assisted translation
https://lwn.net/Articles/872649/

syzbot kernel-fuzzing system (内核模糊测试系统)发现了许多 bug,但是,由于其中不少 bug 看起来严重性相对比较低,因此在开发者这边注重度较低。在最近举行的北美 Linux 安全峰会(Linux Security Summit North America)上的一个讲座介绍了一些针对 syzbot 所发现的错误进行进一步研究的工作,结果相当令人担忧。与其被称为是一堆很难被攻击者利用或不可能利用的 bug,其实事实上有许多更严重的问题潜伏在其中。

SyzScope

峰会第一天的第一位演讲者是加州大学河滨分校的博士生 Xiaochen Zou,他介绍了他和他的同事对 syzbot (它使用 syzkaller coverage-guided fuzzer)在 Linux 内核中报告的 bug 进行的分析。在过去的四年里,syzbot 报告了大约 4000 个错误,其中 3000 个已经被修复。他说,这些错误主要分为八类,但其中只有部分类别是表示出现了 security bug。这些都是经典的、严重的内核安全漏洞,比如 free 后仍在使用、多次 free,和越界写入。它们大多是由 syzkaller 检测中的 Kernel Address Sanitizer(KASAN)发现的。

[Xiaochen Zou]

还有其他几类也需要修复的 bug,但它们往往得到的关注较少。这些 bug 包括 kernel 或者 Sanitizer 里的 assertion 以及 general protection faults(例如无效的指针解析引用)。此外,有些允许读取内存内容的 bug 可以导致信息泄露,比如泄露内核地址,但这些通常无法用来破坏内核,Zou 指出。研究人员将这些归为低风险的漏洞。属于低风险类别的错误平均就需要更长的时间来修复,而且也需要更长的时间来 backport 到之前的旧内核上。syzbot 报告的 bug 数量非常多,使得内核社区顾不上在所有地方来完成 fix。

如果那些 fix 速度较慢的错误确实是低风险的,那也就无所谓了,但研究发现,许多这样归类的 bug 实际上并不是低风险。除此之外,Syzbot 的报告也并不总是能说明清楚这个 bug 会带来的全部影响。更糟糕的是,有一些方法可以从这些低风险的 bug 中自动发现更高风险的一些后果。SyzScope 就是一个旨在揭示那些被报告为低风险类别的错误的高风险影响的工具。SyzScope 不是为了自动完成完整漏洞入侵(create full exploits),因为已经有许多其他研究项目在解决这部分问题了。比如说 FUZE 专注于对那些 use-after-free bug 来进行这类工作,而 KOOBE 是针对越界写入的漏洞。

Zou 说,研究人员有几点看法,从而开启了 SyzScope 的开发。Syzbot 只显示它在测试的执行路径中发现的第一个 bug,通常它就会停止在这里并把这个漏洞报告出来。这样做是有其合理性的,因为 Syzbot 正在寻找 bug,不一定是要找到与 security 有关的 bug。但是,它可能会忽略它所报告的 bug 之后的更多、更危险的影响,这可能就会淡化 bug 的风险,从而可能导致它不会被优先及时地 fix。

他说,即使你让 fuzzing 测试继续往后跑,但其实有几种类型的后续影响是它无法发现的。比如 control-flow hijacking 和写入某些值或者地址(无论是任意写入还是受限写入)都不能被 sanitizers、kernel assertion、或 syzkaller 使用的其他机制检测到。

他举了一个例子:KASAN 检测到的越界读取,而 syzbot 也报告了出来。这里可以变成向任意地址写入 null。但是,由于这个检测依赖于这个越界内存位置的中的具体的值,因此 fuzzing 检测将无法发现这个问题。只有当越界位置的内存被专门准备好时,才能达到这个效果。

heap spraying 是一种让攻击者用来把内存安排成这种形式的技术。不过,除了写 null 之外,在 syzbot 相关漏洞的再后面一些的位置,是采用来自越界内存的内容作为地址进行的函数调用,这也是可以由攻击者控制的。于是这就会导致 control-flow hijacking 以及对 kernel 的全面攻破。

但后续这些进一步的影响是由人类中的专家来发掘出来的,而不是由 syzkaller 或其他工具所发现的。研究人员希望有一种方法能自动发现这些类型的问题。Fuzzers 无法像攻击者常做的那样来对 use-after-free 或者越界内存的内容进行控制。

Symbolic execution

有一种技术就可以完成这种工作:symbolic execution。通过在对程序进行分析中使用 symbolic value 而不是具体的值,就可以通过 symbolic execution 来很有效地模拟出 heap spraying 的结果。比如它可以算出来需要存储什么值、以及应该把它们放在哪个位置,就可以使得这个函数能在攻击者所选择的位置被调用。

SyzScope 有两种操作模式,都是在寻找隐藏在低风险报告背后的高风险 bug。在第一种模式下,它会对 syzbot 报告的尚未解决的 bug 来进行静态分析(static-analysis)以及 symbolic execution。在另一种模式中,它会使用 fuzzing (模糊分析)、static analysis 以及 symbolic execution 来针对已经 fix 的 bug 进行分析。后者主要加入了 fuzzing 来寻找原来那个 bug 的后续影响位置,并使用 bug fix patch 来验证这里发现的新 bug 是原来那个 bug 的后果。

为了节省时间,Zou 说他将跳过关于 static analysis 部分的介绍。这部分是可选的,只是用来协助 symbolic execution 的步骤。它实际上是一个优化而已。

这里使用了一个限制版的 fuzzing 分析来试图找到与原始 bug 有相同 root cause 的一些其他有错误的上下文,然后把这些信息用在 symbolic-execution 中,看看它们是否真的是高风险的 bug。与 syzbot 不同的是,这种 fuzzing 处理虽然也使用了 syzkaller,但是并不会在发现 bug 时就停止。相反它会继续运行来看看还能发现什么。这个 fuzzing 检测会从 syzkaller 生成的的用来展示原始问题的概念验证性代码开始,然后使用 "conservative mutating strategy" 来尝试发现 use-after-free bug、out-of-bound write 等问题。它使用 bug-fix patch 来确定哪些新的上下文是原来的已经 fix 的 bug 有关的。如果这些新的上下文中的检测在使用打了 patch 的内核时没有报错,那么这些问题就被判定为隐藏在原先 bug report 之下的高风险 bug,而当时这些 bug 都被按照低风险 bug 来处理的。

fuzzer 会用 impact feedback(影响信息反馈)来增强 syzkaller 的代码覆盖率反馈(code-coverage feedback)。它希望能找到那些具有较大影响的 bug,以便来找到高风险 bug。代码覆盖率反馈有时会引导 fuzzer 去寻找全新的错误,而这并不是他们的工作目标。

symbolic execution 阶段使用了 QEMU,会在 KASAN 报告问题的地方设置一个断点(breakpoint),而且先构造并触发该 bug。然后启动 "angr" (他们的 symbolic-execution 引擎)。angr 会从 KASAN 的报告中找到越界的内存地址并将其 "符号化(symbolize)"。QEMU 中的寄存器值被发送给 angr,并且它也可以从 QEMU 中动态获取内存中的内容。

该引擎会寻找会对 KASAN 报告的越界内存范围内的数值进行操作的某些类型汇编指令。这使它能够检测到各种类型的利用缺陷的方式。例如,如果传递给 kfree() 的值来自可以被控制的内存位置,那么它就会被标记为 invalid free。类似地,对来自越界内存地址的调用是产生 control-flow-hijacking 攻击的一种方式。通过这种方式来检测出五种不同类型的高风险影响。

Results

研究人员对 syzbot 报告出来的近 1200 个低风险漏洞进行了实验。对每个漏洞进行了 3 小时的 fuzzing 处理以及 4 小时的 symbolic execution。总的来说,该实验发现了 147 个低风险漏洞导致的高风险影响问题。很多低风险漏洞都有许多其他一些影响,其中很多都会带来高风险类别的后果。例如,发现了 51 个 control-flow hijacking 的问题,这个数字包括了 syzbot 对于低风险类别中报告出来的已经 fix 的和尚未 fix 的 bug 进行的分析结果。在 syzbot 报告的内容之外,还发现了大约 3200 个与之无关的安全问题。

针对大约 5% 的全部 impact 来仅仅依靠 fuzzing 就发现了接近半数的 high-risk bug。如前所述,fuzzing 方式只能发现那些不需要控制越界内存内容的安全问题。因此对于已经被修复的 bug (可以使用 fuzzing 阶段分析了),平均每个被测试过的内核 bug 都有接近 28 个进一步的安全问题(further impact)。从尚未解决的 bug 中进行的测试平均每个都发现了约 17 个额外的安全影响。

symbolic execution 报出了这个实验中所发现的另一半的高风险漏洞,包括所有 34 个由 syzbot 报告但仍未在内核中修复的漏洞。它还报出了绝大部分(95%)的 impact,包括所有的超高风险 impact 都是它报出来的,比如 control-flow-hijacking 和对任意地址的写入问题。

研究人员向 CVE 维护者提交了 32 个高风险漏洞,其中 8 个被分配了 CVE 编号(可以在 Zou 的幻灯片 28 中看到)。他们的论文将在 2022 年 8 月举行的第 31 届 USENIX 安全研讨会上发表。邹说论文应该很快就能拿到。

多年来,syzbot 的输出的大量 bug report,以及内核开发人员无法跟上这个速度,一直是人们比较担心的一个问题。这次的发现只会更加加剧这些担忧。毫不意外我们会发现黑帽子(恶意攻击者)或者政府机构正在使用类似的技术来将看似不太有害的漏洞变成能用来完全攻破内核的方法。事实上,如果他们不这样做,那才是令人惊讶的。在某种程度上,这些发现都表明来根据 syzbot 报告的 impact 来确定 bug 的优先级的做法,可能经常低估了危险性,但这些数据确实有利于证实 "所有 bug 都是 security bug" 的观点,这种态度在一些内核开发社区中是很流行的。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~



浏览 36
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报