TCP-Fuzz: Detecting Memory and Semantic Bugs in TCP Stacks with Fuzzing (USENIX ATC 2021)
摘要
TCP 栈接受相互依赖的数据包和系统调用,因此生成有效的测试用例具有挑战性。其次,TCP栈有各种复杂的状态转换,但现有的测试方法以覆盖状态而不是覆盖状态转换为目标,因此它们的测试覆盖范围有限。
作者设计了一个名为 TCP-Fuzz 的新型模糊测试框架,以有效地测试TCP 堆栈并检测错误。
- 基于依赖的策略,考虑数据包和系统调用之间的依赖关系,以生成有效的测试用例
- 一种转移引导的模糊测试方法,它使用一种名为分支转移的新覆盖度量作为程序反馈,以提高状态转移的覆盖率
- 一个差分检查器,它比较多个 TCP 堆栈的相同输入的输出,以检测语义错误。
背景
TCP 栈接受的数据包和系统调用之间应该 有依赖关系,否则它们将被 TCP 栈简单地忽略而不进行深度处理。 具体来说,存在三种依赖关系:
- Syscall-syscall 依赖关系。 例如,当 连接被动打开时,应用程序必须依次调用一系列系统调用,包括 socket、 bind、 listen 和 accept 。否则,应用程序无法成功 建立 TCP 连接。
- 数据包-数据包依赖性。 例如, 建立连接后,每个数据包的源端口和目的端口 应该是固定的。否则,TCP 堆栈会识别出无效的数据包,因此直接丢弃 它们而无需进一步处理。
- 系统调用包依赖性。 例如,系统调用 accept 仅在 TCP 堆栈接收到 最后一个三向握手数据包后才返回。
技术
- 基于依赖的策略生成有效的测试用例:
(1)突变型选择提供了五种可用的变异类型(包括删除、添加、替换和两种更改),随机选择一个突变类型来按顺序处理输入序列中的每个条目
(2)基于依赖的生成包和系统调用之间有三种依赖关系,如果一个输入序列违反了这些依赖关系,则认为它是无效的,可以被TCP栈简单地忽略掉。因此,为了生成更有效的测试用例,作者考虑这些依赖关系来生成输入序列中的每一项。考虑该项与之前处理的项之间的依赖关系。
考虑到每个TCP栈都是按照RFC文档和系统调用约定实现的,作者将这些依赖规则适用于所有TCP栈。
为了测试TCP栈是否正确地遵守这些依赖规则,作者还通过故意违反包-包和系统调用-包依赖规则,以很小的概率生成一些异常的输入序列。事实上,这样的输入序列在检测异常处理的RFC违规时非常有用。
2. 状态转换引导的模糊方法提高状态转换的覆盖
对于给定的输入序列,当处理该序列中的每一项(一个系统调用或包)时,TCP堆栈的状态总是改变的。也就是说,每一个这样的项都会影响TCP栈的执行情况。因此,在处理每一项后,可以认为TCP堆栈达到了一个新的状态。这种状态可以用分支覆盖(即代码分支的覆盖)来描述,正如现有的fuzzing方法所做的那样。
因此,状态转换可以描述为由于两个相邻输入项而在两个被覆盖状态之间的转换,即这些输入项之间分支覆盖的变化。受到这个想法的启发,作者提出了一个名为分支转换的新的覆盖度量来描述状态和状态转换。对于给定的输入序列,分支转换被表示为一个向量,该向量存储当前输入项的分支覆盖,以及当前输入项和先前输入项之间分支覆盖的变化。
每个状态都使用一个分支覆盖向量来描述,包含TCP堆栈代码中每个分支的执行情况(覆盖或未覆盖),当前输入项和前一个输入项之间的状态变化被表示为它们的分支覆盖向量(当前-前一个)的相减。
如果它覆盖了新的转移分支->interesting,并将其放入种子语料库中以备将来的突变。
大部分fuzzing使用的afl。
3. 差异检查器检测语义错误
向多个TCP栈提供相同的输入序列,然后记录它们的输出(包括系统调用的返回值和参数以及来自TCP栈的响应包),最后比较这些输出,以识别和报告不一致性。用户可以检查这些不一致,以找到相关的语义错误。
框架
- 代码分析器它首先使用Clang将TCP栈的源代码编译成LLVM字节码。然后,它检测LLVM字节码中的每个代码分支。最后,它编译修改后的LLVM字节码以生成可执行的TCP栈。
- 测试用例生成器
- 监控收集所覆盖的分支并计算分支状态转换,提供反馈。调用Packetdrill接口来接收每个TCP堆栈的输出,将它们提供给差异检查器。
- 错误检查内存bug和语义bug。
(1)现有的bug清除程序(比如ASan和MSan)通过在运行时监视内存访问来检测内存bug。
(2)数据验证器。检测导致TCP栈错误数据传输的语义错误,因为确保数据传输的正确性。检查:TCP栈通过read调用接收到的数据是否与发送到TCP栈的数据包中存储的数据相同—-调用write从TCP栈发送的数据是否与远端接收到的报文中存储的数据相同。
(3)差分检查程序。比较相同输入的多个TCP栈的输出,以便检测语义错误。