Creating a Nix Workflow to Fuzz netconsd

Michael Lynch

创建 Nix 工作流来对 netconsd 进行模糊测试

最近,每当我睡不着的时候,就会找一些软件来做模糊测试(fuzzing)。

本周早些时候,我想起了 Fady Othman(法迪·奥斯曼)的文章 “Meta Bug Bounty — Fuzzing ’netconsd’ for fun and profit.”。这是一篇关于如何彻底地对代码进行模糊测试的优秀教程。

和大多数关于模糊测试的博客文章一样,我发现这项工作不太容易复现,因为读者需要自己弄清楚如何复现作者的环境和工具链。

我打算尝试用 Nix 制作一个易于复现的 Othman 模糊测试器版本,就像我之前对 xpdf 所做的那样。我那篇关于 xpdf 的文章要详尽和完善得多,而这些只是给好奇者的一些快速笔记。

fuzz-netconsd

这是我花了几个小时为 netconsd 创建的模糊测试工作流:

如果你安装了 git 和 Nix,就可以用以下命令运行我的工作流:

nix run gitlab:mtlynch/fuzz-netconsd

这是我写的第一个模糊测试器:模糊测试工具不是通过 shell 执行编译好的二进制文件,而是直接通过函数调用进入被测代码。在 honggfuzz 和 AFL++ 中,这被称为“persistent mode(持久模式)”,我猜是因为模糊测试器可以让一个进程持续存在,而不是每次模糊测试运行都生成一个新进程。

通过函数调用进行模糊测试很有意思,因为即使目标代码根本没有发布共享库,你也可以这样做。我是在工作流的 installPhase做到这一点的:把包含我想调用的代码的 .o 文件以及对应的 .h 头文件复制到该步骤的 Nix 输出目录中。

拿到所需的头文件和目标文件后,我写了一个简单的测试 harness(测试驱动程序),它只包含刚好够调用我要模糊测试的函数 ncrx_process 的代码:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "ncrx.h"

int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
  // Convert the random bytes of the payload to a null-terminated string.
  char *payload = (char *)malloc(len + 1);
  if (!payload) return 0;
  memcpy(payload, buf, len);
  payload[len] = '\0';

  struct timespec ts;
  if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
    perror("clock_gettime");
    return 1;
  }

  uint64_t now = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;

  struct ncrx *ncrx = ncrx_create(NULL);

  // Call the function that we're fuzzing.
  ncrx_process(payload, now, 0, ncrx);

  // Clean up the resources we allocated.
  ncrx_destroy(ncrx);
  free(payload);

  return 0;
}

我发现持久模式下的模糊测试比预想的要容易。我甚至不需要深入了解 netconsd。我至今仍不完全清楚它到底是做什么的,但我已经理解到足以在模糊测试器下调用它的一个解析函数。

我可能不会发现什么问题

Othman 报告说他的模糊测试工作达到了 100% 的覆盖率,这是极其彻底的。

我查看了 netconsd 的提交历史,自 Othman 的工作之后几乎没有任何活动。他没有在文章中明确说明,但我怀疑下面这个提交就是修复他所发现的漏洞的改动:

我怀疑在这个时间点上通过模糊测试能发现的东西不多。在我的模糊测试器运行了 12 个小时没有出现任何崩溃之后,我就把它停掉了。

未完成的工作

  • Othman 使用 klee 工具为模糊测试语料库生成了边界情况输入。我没有实现这一点,但它可以很好地融入这个工作流,因为 klee 已经被 Nix 打包了。
  • 我用的是 honggfuzz 而不是 Othman 所用的 AFL++。我更喜欢 honggfuzz 的简洁性,但 Othman 对 AFL++ 的各种参数足够熟悉,能够获得更高的覆盖率。

原文由 Michael Lynch 发布

本文章由 stealth/ox-alpha 进行翻译