欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

通过libFuzzer实现结构敏感型的模糊测试技术(下)

来源:本站整理 作者:佚名 时间:2019-03-11 TAG: 我要投稿

针对状态API的模糊测试
到目前为止,我们已经讨论了针对使用单个结构化输入的API的模糊测试方法。不过,有些API可能与前面介绍的API差距甚大。例如,有些API不会直接使用数据,相反,它们是由许多函数组成的,并且仅在API处于特定状态时,这些函数才起作用。这种有状态API对于网络软件来说是非常常见的。对于这种API来说,使用protobuf进行模糊测试也很有效。这时,我们只需定义一个描述API调用序列(或跟踪)的protobuf消息,并实现一个函数来执行跟踪。
示例:gRPC API Fuzzer
虽然gRPC的API Fuzzer并没有使用libFuzzer的自定义mutator或protobuf,但是,它仍然是针对有状态API的模糊测试的一个很好的简单示例。在这里,Fuzzer会使用字节数组,每个单独的字节都被解释为针对特定API函数的单个调用(在某些情况下,后面的字节用作参数)。
    switch (grpc_fuzzer_get_next_byte(&inp)) {
      default:
      // terminate on bad bytes
      case 0: {
        grpc_event ev = grpc_completion_queue_next(...
      case 1: {
        g_now = gpr_time_add(...
这个模糊测试目标适用于突变型的模糊测试引擎,并产生了80多份安全漏洞报告,其中一些是用libFuzzer发现的,另一些是用AFL发现的。
然而,这种方法有一个缺点,即fuzzer生成的输入对于模糊测试目标本身之外的代码来说是没有任何意义的,并且,这些输入会因目标代码的微小变动而失效。同时,这些输入也不是人类可读的,使得对由此发现的安全漏洞的分析更加复杂。
示例:Envoy头部到Fuzzer的映射
实际上,有一个Envoy模糊测试目标采用了一种不同的方法来对有状态API进行测试:它使用定制的protobuf消息类型对动作序列进行编码,并实现了针对这些类型的播放器。
DEFINE_PROTO_FUZZER(const test::common::http::HeaderMapImplFuzzTestCase& input) { ...
  for (int i = 0; i
这个模糊测试目标已经至少发现了一个security regression:漏洞,修复补丁。该漏洞的Reproducer输入是一个带有消息文本的可读文件。
与前面将测试动作编码为字节序列的方法相比,使用protos对有状态API进行模糊测试时,不仅速度要慢一些,而且,测试过程也更复杂一些。不过,这种方法也有其优点:这种方法更加灵活,同时,也更加易于维护,因为protobuf类型比自定义字节编码更容易理解,也更易于扩展。
示例:Chrome IPC Fuzzer
由于Chrome含有许多有状态的API,因此,在代码审查期间,人工审查这些API的话,难度非常大,这使得针对这些API的模糊测试技术,很容易找到有价值的漏洞。在这方面,一个很好的例子就是AppCache子系统。这是一种针对HTTP的缓存机制,旨在使某些应用程序可脱机使用。
在Chrome中,该机制是在沙盒渲染器进程和特权浏览器进程之间的接口中实现的,它们运行于unsandboxed状态。下面是一个可用于渲染器进程的API:
// AppCache messages sent from the child process to the browser.
interface AppCacheBackend {
  RegisterHost(int32 host_id);
  UnregisterHost(int32 host_id);
  SetSpawningHostId(int32 host_id, int32 spawning_host_id);
  SelectCache(int32 host_id,
              url.mojom.Url document_url,
              int64 appcache_document_was_loaded_from,
              url.mojom.Url opt_manifest_url);
  SelectCacheForSharedWorker(int32 host_id, int64 appcache_id);
  MarkAsForeignEntry(int32 host_id,
                     url.mojom.Url document_url,
                     int64 appcache_document_was_loaded_from);
  [Sync] GetStatus(int32 host_id) => (AppCacheStatus status);
  [Sync] StartUpdate(int32 host_id) => (bool success);
  [Sync] SwapCache(int32 host_id) => (bool success);
  [Sync] GetResourceList(int32 host_id) => (array resources);
};
对于单个AppCacheBackend来说,实际上就是一个有状态的对象,它们在浏览器进程中运行,负责处理所有这些消息。作为其正常操作的一部分,后端也可以发出HTTP请求。而针对这些请求的响应内容,实际上会影响控制流。因为它们是外部可用的,所以它们也是攻击面的一部分。
了解这些后,我们可以编写一个protobuf规范,让我们可以对后端执行一系列API调用,并处理它发出的所有请求。由于Chrome的代码允许我们覆盖本地模糊测试输入的网络数据源,从而简化了测试过程。
以下是我们的fuzzer protobuf规范的片段:
message Session {
  repeated Command commands = 1;
}
 
// Based on blink::mojom::AppCacheBackend interface
// See third_party/blink/public/mojom/appcache/appcache.mojom
message Command {
  oneof command {
    RegisterHost register_host = 1;
    UnregisterHost unregister_host = 2;
    SelectCache select_cache = 3;
    SetSpawningHostId set_spawning_host_id = 4;
    SelectCacheForSharedWorker select_cache_for_shared_worker = 5;

[1] [2]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载