Logo
Overview

论文笔记: μFUZZ: Redesign of Parallel Fuzzing using Microservice Architecture

July 30, 2024

Abstract

fuzzing技术被广泛运用于漏洞挖掘中,研究者也开发了不同的方法,能够让 fuzzing 并行运行,从而提高挖掘的效率。但是先前出现的项目都存在一些问题,降低了多线程挖掘的效率:

  • 对于状态的同步,需要暂停 IO,浪费 CPU 算力
  • 同步太慢时,fuzzing 线程无法及时得到更新,不能达到最优效果
  • 同步太快时,同步的线程占用过多 CPU 资源,开销太大。

本论文提出了一种新的方法μfuzz,并且给出了实现代码,通过微服务的方式减少上述问题对多余资源的开销,从而加快 fuzzing 的速度。

1 Introduction

总结了现有技术中分布式 fuzzing的解决方案,列举了上述提到的几个问题,引出了本文项目的微架构方案,写出了这个项目在测试项目中和其他项目的分数差别。

2 Problem

2.1 How Existing Parallel Fuzzing Works

主要讲解了现有主流的分布式 fuzzing 技术的架构和方案,如图 Fig.1,在一个实例中维护状态,这会导致状态同步的不及时性,和在进行同步时对 CPU 的浪费。

2.2 Limitation of Existing Approaches

讲解了现有分布式解决方案的问题:

  • 因为 IO 瓶颈导致的 CPU 浪费。(Table 1,2)
    • 测试程序带来的 IO 浪费(系统调用,压缩,etc.)
    • 状态同步带来的 IO 浪费
  • 测试状态没有被实时更新。 (Fig.2)
    • 一个实例可能使用过时的策略和方法进行 fuzz,这个策略可能是当前实例最优,但不是全局最优,因为状态更新是定时完成的。
    • 但是同样,也不能对一个实例过于频繁地进行状态更新。
2.3 Microservice Architecture

微服务架构的好处:

  • 多个松散的但是可组织的服务,并行运行。我们可以将一个 instance 的多个状态分装为不同的服务。
  • 每个服务都不依赖于其他的服务,独立运行。
  • 每个服务的能力都可以通过调整并行线程的数量来调整。
2.4 Our Approach

笔者设计了一种比较不错的微服务架构来完成 fuzzing 的过程。

  • 重新设计的微服务架构:把传统 fuzzing 中的 state 拆分得到几个不同的微服务
  • 重新设计的状态:拆分后,我们将状态也进行拆分:

    我们要求:

    1. 状态是功能完整的
    2. 本地最优->接近全局最优的聚合。

3 Design

Fig.3是μfuzz 的整体框架。

接下来我们会在3.1中介绍从 instance 到几个不同的 Microservice 的方法,3.2中讲解用来使不同 service 之间协作的输出缓存机制,3.3讲解负载均衡的方法,3.4中讲解状态设计,3.5中讲解zero-copy communication 方法。

3.1 From Monolith to Microservice

每个 service 的基础架构如图 Fig.4:一个 service 中有 Input Dispatcher,几个不同 Worker 和剩余的 Output Caching Queue,同时它维护一个 state。我们按照如下方法对传统的 fuzzing 进行拆分:

  • 每个服务只关注 fuzzing 的一个部分
  • 每个服务不需要其他服务的 state 来完成。
  1. Corpus Management Service

    语料管理服务用来维护一组有趣的测试用例和它们的元数据,如性能分散。它通过一个优先级算法来选择最优的语料进入下一步生成。

  2. Text Case Generation Service

    测试样例生成服务使用从上一步输入的“有趣”的语料,通过变异等策略来生成新的测试样例。

  3. Execution Service

    运行服务将上一步生成的测试样例输入程序运行。

  4. Feedback Collection Service

    从运行服务中收集运行结果,对这些结果进行分类,挑选出“有趣”的结果发送回语料管理服务中。

这就是这个系统的工作流程。每个设备都是单独运行,不受影响的。

3.2 Concurrency by Output Caching

每个 service 都是有输入和输出的,我们通过输出缓存来解耦输出,从而实现程序的连续运行。

如 Fig.4 所示,一个 worker 完成了运行之后将结果发送到 Output Caching Queue,而不是下一个 service 的输入。当下一个 service 准备好了之后,这个 queue 才会将内容发送。

拥塞控制:但是如果 output queue 中存入了太多的内容,它会占用大量 CPU 资源,让下一个进程无法清理输入。所以需要对 OutputCache 进行限制,从而可以使内容生成和输入消耗达到平衡。

3.3 Parallelism by Load Balancing

每个 service 的 worker 数量都设置为CPU 核心数量,然后维护一个空闲核心的队列,当一个空闲核心进入队列且任务队列中有任务时,给空闲核心分配任务。

3.4 Avoid Synchronziation by State Partition

接下来设计状态来避免同步。

μfuzz 进行两级状态分级:第一级中,μfuzz 将状态分配给它的服务,以便服务能独立工作。第二级中,每个服务将状态分配给不同的 workers。

State Partition:我们对状态进行分区,固定大小的状态进行静态分区,可变大小的进行动态分区。算法如Alg.1 所示。每个 worker 负责一部分状态的内容。

Result Accumulation:对每个 worker,我们需要把结果整合。(在本文中是 Output Cache Queue 做的这一步)

State Updates:状态由 service 中的worker更新。

3.5 Zero-Copy Communication

复制的参数会造成很多不必要的 IO 操作,可以通过共享的指针来传递参数。

但是这样操作可能出现一些安全隐患,对指针添加所有权限制来阻止不安全的内存访问。

4 Implementation

μfuzz 由 rust 实现,共用了 9534 行代码,见 Table 5

  • 使用 tokio 来实现多线程
  • 将所有的 service 运行在一个进程中来共用内存。

5 Evaluation

用了一些测试方法对比了其他的几个现有的 Fuzzer,且测试中发现了新的漏洞。

6 Discussion

本章讲解了 μfuzz 可以改进的点。

6.1 Distributed Fuzzing

可以实现 RPC 调用来完成远程调用,从而实现分布式的 fuzz。给出了网络成为 IO 瓶颈的解决方法:Prefetching。

6.2 Support More Mutation Strategy

应用更多不同的进化方法。

6.3 Support Collaborative Fuzzing

实现多种 fuzzing 服务的结合。

7 Related Work

讲解了一些相关的工作,比如 fuzzing strategy 的改进,加速 fuzzing ,和多线程 fuzzing。

comment

留言 / 评论

如果暂时没有看到评论,请点击下方按钮重新加载。