RESOLVERFUZZ

RESOLVERFUZZ: Automated Discovery of DNS Resolver Vulnerabilities with Query-Response Fuzzing 论文分享

Zhang, Q., Bai, X., Li, X., Duan, H., Li, Q., & Li, Z. (2023). ResolverFuzz: Automated Discovery of DNS Resolver Vulnerabilities with Query-Response Fuzzing. ArXiv, abs/2310.03202.

pdf链接:usenix.org/system/files/sec23winter-prepub-246-zhang-qifan.pdf

RESOLVERFUZZ:使用查询-响应模糊测试自动发现DNS解析器漏洞

RESOLVERFUZZ通过专注于简短的查询响应序列来执行受限状态模糊处理,这是目前查找解析器错误的最有效的方法。其次,为了生成更有可能触发解析器错误的测试用例,本文将基于概率上下文自由语法(PCFG)的输入生成与查询和响应的字节级突变相结合。最后,利用差分测试和集群来识别缓存中毒等非崩溃漏洞。

现存的解析器漏洞检测方法局限

  1. 大多数已知的解析器漏洞都是非崩溃漏洞,现有的检测手段无法直接检测到
  2. 缺乏严格的规范,无法将测试用例归类为解析器错误
  3. 解析器是有状态的,由于输入空间大,有状态模糊仍然具有挑战性

提出问题

如何使分析仪器能够更准确地进行流量分类,在不同的流量中捕捉隐式的和鲁棒的模式。

贡献

  1. 对DNS CVE进行了全面研究。
  2. 根据CVE研究的见解,开发了一个新的黑盒模糊系统RESOLVER-FUZZ。它执行受限的查询响应模糊,以在解析器上发现有效的错误。
  3. 为RESOLVERFUZZ开发和/或调整一套技术,包括DNS本地化、基于PCFG的测试生成、差异测试等。
  4. 针对6个主流解析器对RESOLVERFUZZ进行了评估,发现了23个漏洞。

DNS

DNS(Domain Name System)是一个分布式数据库系统,它将域名与IP地址进行映射,以便用户可以通过易记的域名访问互联网上的各种资源。DNS系统由多个组件组成,包括域名服务器、解析器和DNS协议等。

域名服务器存储了大量的域名与IP地址的映射关系,当用户输入一个域名时,解析器会向域名服务器发送请求,以获取对应的IP地址。域名服务器可以分为多个级别,包括根域名服务器、顶级域名服务器和权威域名服务器,它们协同工作,帮助解析器找到正确的IP地址。

DNS解析器

解析器是用户设备或网络设备上的软件,它负责将用户输入的域名转换为对应的IP地址。解析器首先会查询本地缓存,如果没有找到对应的IP地址,就会向域名服务器发送请求,获取正确的IP地址。解析器还可以进行递归查询,即向多个域名服务器发送请求,直到找到正确的IP地址为止。

DNS查询和响应的格式

遵循RFC 1034,RFC 1034定义了DNS查询和响应的格式,这些格式是DNS系统中用于进行域名解析的标准。以下是DNS查询和响应的格式遵循RFC 1034的主要内容:

DNS查询格式:

  • 查询报文格式遵循RFC 1034中定义的标准格式,包括查询标识、查询类型、查询类别等字段。
  • 查询报文通常包括一个或多个查询问题部分,每个问题部分包含一个域名、查询类型和查询类别。

DNS响应格式:

  • 响应报文格式同样遵循RFC 1034中定义的标准格式,包括响应标识、响应类型、响应类别等字段。
  • 响应报文通常包括一个或多个资源记录部分,每个资源记录包含了对查询的响应信息,包括域名、TTL(生存时间)、数据长度和实际数据等字段。

在RFC 1034中,还定义了DNS报文的各个字段的具体含义和格式要求,以及报文的传输方式和处理规则。这些规范使得不同的DNS实现能够遵循统一的标准,确保了DNS系统的互操作性和稳定性。

下图是一个DNS消息的示例

image

DNS相关漏洞的分布和根本原因

下表是本文对主流DNS软件的DNS CVE研究结果

image

  • F1:大多数CVE都是关于解析器的。本文总共确定了与6个研究的DNS软件相关的291个CVE(132个CVE与其他DNS软件有关)。其中,245(84%)是关于解析器(例如,递归和转发器模式的CVE-2019-6477和CVE-2020-8621)。只有46个CVE是关于名称服务器的(例如,CVE-2020-8619和CVE-2017-3143)。
  • F2:DNS软件中的多样化CVE。虽然BIND在CVE1的数量上占主导地位,但在其他软件(Technitium除外)中也发现了大量CVE。此外,本文发现245个CVE中只有13个CVE影响所有软件(例如,CVE-2020-12662下的NXNSAt-tack),这表明DNS软件的实现多种多样。
  • F3:很大一部分cve与崩溃无关。与先前研究TCP堆栈中的CVE的结果一样,本文发现不会触发软件崩溃的漏洞占很大一部分(245个cve中有109个)。主要后果包括缓存中毒(46个CVE,例如,在CVE-2002-2213和CVE-2006-0527下缓存非法记录)和资源消耗(39个CVE,例如,在CVE-2022-2795和CVE-2021-25219下花费过多的资源来处理DNS查询)。在136个与崩溃相关的bug中,只有43个是由CVE-2020-8625和CVE-2021-25216下的缓冲区溢出等内存损坏引起的。其他主要由断言失败触发(例如,CVE-2022-0635和CVE-2022-3080)。
  • F4:DNS消息的几乎每个字段都有相关的CVE。示例包括查询名称(CVE-2020- 8617)、查询类型(CVE-2022-0667)、查询标志(CVE-2017-15105)、rcode(CVE-2018-5734)、rdata(CVE-2013-4854)、TTL(CVE-2003-0914)等。
  • F5:大多数CVE都是通过非常短的消息序列触发的。本文发现222/245(91%)的CVE可以通过仅发送一个客户端查询或ns-响应来触发。其中一个例子是CVE-2022-3736。对于其他需要更长序列的CVE(例如,CVE- 2022-3924),需要许多客户端查询来触发错误。

RESOLVERFUZZ的设计目标和挑战

设计目标

RESOLVERFUZZ旨在取消覆盖上述威胁模型下的漏洞。 主要专注于四种类型的漏洞,缓存中毒、资源消耗、服务崩溃和内存损坏,因为这四种类型的漏洞是DNS软件的主要问题。 RESOLVERFUZZ应该高效地以高吞吐量测试解析器。此外,RESOLVERFUZZ应该能够以高精度判断测试输入是否会导致漏洞发现。

挑战

C1:效率。定期DNS解析预计会有显著的延迟,因为客户端、解析器和多个名称服务器之间需要网络通信。因此,实现解析器模糊的高吞吐量并非易事。

C2:突变。广泛使用的灰盒模糊器,如AFL,用基于覆盖的met-ric突变输入。然而,此类指标没有就测试输入的哪一部分应该突变提供足够的指导,但DNS消息包含许多与错误相关的字段。

C3:有状态的模糊。与在无状态模式下运行的名称服务器不同,解析器是有状态的,其状态取决于缓存记录、配置等。由于输入序列的搜索空间很大,国有服务被认为是网络模糊的主要挑战。

C4:Oracle。非崩溃错误在CVE中有很大份额。然而,缺乏检测器来检测此类错误。相反,像AddressSanitizer这样的可以检测到崩溃错误。差异测试已用于发现非崩溃的语义错误,但之前的工作都没有为DNS构建ora-cle。此外,DNS解析器之间的不一致很常见,其中许多并不表明存在漏洞。

RESOLVERFUZZ的工作流程

在第一阶段,测试基础设施加载不同实现的解析器并配置环境。应用了许多优化技术来增加DNS查询和响应的吞吐量(C1)。然后,测试用例生成器对客户端查询和ns响应执行基于语法的突变(C2)。虽然解析器是有状态的(C3),但根据本文对CVE的研究,在大多数情况下,触发错误只需要一个客户端查询和/或一个ns-响应的简短序列。因此,本文简化了有状态模糊,以模拟短序列。最终,对于我们的数据转储收集的数据,包括缓存、日志、响应和流量,开发了不同的程序来检测本文提到的不同类型的漏洞。本文应用差分测试来识别解析器之间的不一致,以捕获缓存中毒错误。为了解决(C4)问题,本文开发了一种新方法,对不一致情况进行聚类,并对异常情况进行警报,因此将大大减少错误调查的手动工作。

下图是RESOLVERFUZZ的流程图

image

测试基础设施

测试基础设施用于模拟DNS查询和针对解析器的响应,并收集跟踪以待以后分析。该基础设施主要包括一个DNS客户端和一个名称服务器,该名称服务器发出由本文的模糊器(攻击者客户端和攻击者服务器)生成的消息,一个测试调度器和一个跟踪收集器。

测试调度器

这个中央组件初始化DNS组件,包括攻击者客户端、攻击者服务器和解析器。在每轮测试(即一次DNS解析的往返)之间,调度器会重置这些组件。为了高效和完全重置,本文选择用轻量级Docker容器托管这些组件。为了增加测试吞吐量,调度器将命令客户端并行向解析器发送查询,并复制解析器实例。具体来说,调度器将攻击者客户端、攻击者服务器和解析器分组到一个单元中,并同时运行多个单元(使用不同的测试用例)。通过基于容器的隔离,每个解析器实例都可以独立测试。

测试过程
  • 测试调度器初始化Docker网络和n个模拟DNS基础设施单元。
  • 测试调度器从生成器获取测试用例,并将其补丁到攻击者客户端和服务器。
  • 在每个解析器容器启动后,内部监视器收集有关缓存转储、网络流量和进程信息的信息。
  • 当攻击者客户端收到解析器响应时,解析器容器将通过缓存刷新或软件重新启动进行重置,相应的单元将返回到第2步,直到所有测试完成。

测试用例生成器

从两个维度生成测试用例,包括攻击者客户端的客户端查询和攻击者服务器的ns响应。将DNS解析器视为有状态服务,则生成与客户端查询相对应的ns-response。

鉴于DNS消息具有复杂的结构,本文将概率无上下文语法(PCFG)应用于生成客户端查询和ns-responses的模板。

PCFG代码示例:

使用NLTK库来定义了一个简单的PCFG语法,并且给每个产生式赋予了概率值。然后使用ChartParser进行句法分析,对句子 “the cat chased the dog” 进行分析,并输出得到的语法树。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import nltk
from nltk import Nonterminal, nonterminals, Production, CFG

# 定义语法规则
grammar = CFG.fromstring("""
S -> NP VP [1.0]
NP -> Det N [0.5] | N [0.3] | NP PP [0.2]
VP -> V NP [0.6] | VP PP [0.4]
PP -> P NP [1.0]
Det -> 'the' [0.8] | 'a' [0.2]
N -> 'cat' [0.3] | 'dog' [0.3] | 'man' [0.2] | 'woman' [0.2]
V -> 'chased' [0.4] | 'saw' [0.3] | 'bit' [0.3]
P -> 'in' [0.5] | 'on' [0.3] | 'by' [0.2]
""")

# 句法分析
parser = nltk.ChartParser(grammar)
sent = "the cat chased the dog".split()
for tree in parser.parse(sent):
print(tree)
tree.pretty_print()

结论

本文开发了一个新的黑盒模糊系统RESOLVERFUZZ,专为查找DNS解析器漏洞能力而量身定制。RESOLVERFUZZ采用了约束状态模糊、差分测试和基于语法的模糊,达到了很好的效果。RE SOLVERFUZZ在查找解析器错误方面是有效的,发现了23个漏洞,并分配了15个CVE。

知识补充

DNS解析器中4种类型的漏洞
缓存中毒

攻击者篡改解析器的缓存,并将受害者客户端引导到恶意服务器。

DNS缓存中毒漏洞是一种网络安全漏洞,它允许攻击者操纵DNS服务器的缓存,以便将用户重定向到恶意网站或者进行其他恶意活动。这种漏洞可能会对用户的网络安全和隐私构成严重威胁。

缓存中毒漏洞的工作原理是利用DNS服务器的缓存功能,攻击者可以发送虚假的DNS响应,将恶意网站的IP地址存储在DNS服务器的缓存中。一旦DNS服务器缓存了这些虚假信息,当用户尝试访问受影响的域名时,DNS服务器将返回恶意网站的IP地址,使用户被重定向到攻击者控制的网站。

这种漏洞可能导致多种安全问题,包括:

  1. 钓鱼攻击:攻击者可以伪装成合法网站,诱使用户输入敏感信息,如用户名、密码、信用卡信息等。
  2. 恶意软件分发:攻击者可将用户重定向到包含恶意软件的站点,从而感染用户设备。
  3. 窃取信息:攻击者可能窃取用户的个人信息或敏感数据。
资源消耗

攻击者严重消耗解析器的资源来影响其服务质量。

DNS资源消耗漏洞是指攻击者利用DNS协议中的漏洞,导致DNS服务器的资源被过度占用或耗尽的安全漏洞。这些漏洞可能会导致DNS服务器性能下降、服务不可用或拒绝服务攻击(DoS)。

一些常见的DNS资源消耗漏洞包括:

  1. DNS查询放大攻击:攻击者利用DNS协议中的特性,发送大量的DNS查询请求到受害服务器,导致DNS服务器资源被过度占用,从而影响其正常运行。
  2. DNS区域传送攻击:攻击者利用DNS服务器的区域传送功能,向DNS服务器发送大量的区域传送请求,导致DNS服务器资源被耗尽,从而影响其正常运行。
  3. DNS缓存投毒攻击:攻击者通过发送虚假的DNS响应,将恶意域名或IP地址存储在DNS服务器的缓存中,从而影响DNS服务器的正常运行。
非内存崩溃

攻击者在没有内存损坏的情况下终止解析器,例如,通过发送DNS mes- sages来执行具有断言失败的代码。

DNS非内存崩溃漏洞是指DNS软件或系统中的漏洞,其导致的错误或异常不是由内存访问错误引起的。这些漏洞可能导致DNS服务器的异常行为,包括但不限于崩溃、拒绝服务,或者可能被攻击者利用进行远程代码执行等恶意行为。

一些常见的DNS非内存崩溃漏洞类型包括:

  1. 逻辑错误:DNS软件或系统中的逻辑错误可能导致预期之外的行为,例如在特定情况下导致程序进入无限循环或执行不正确的操作。
  2. 资源泄漏:DNS软件或系统中的资源泄漏漏洞可能导致系统资源(如文件描述符、内存、连接等)被耗尽,从而影响系统的正常运行。
  3. 不正确的错误处理:当DNS软件或系统在处理错误时出现问题,可能导致程序的异常行为,如未预料到的退出或崩溃。
内存崩溃

攻击者的DNS消息损坏了解析器内存并终止了解析器。

DNS内存崩溃漏洞是指DNS软件或系统中的漏洞,导致程序在处理域名解析请求时发生内存访问错误,从而导致程序崩溃或产生其他异常行为。这些漏洞通常由于缓冲区溢出或其他内存管理错误导致。

一些常见的DNS内存崩溃漏洞类型包括:

  1. 缓冲区溢出:DNS软件或系统中的缓冲区溢出漏洞可能导致攻击者向程序输入超出其预期范围的数据,从而覆盖了相邻的内存区域,最终导致程序崩溃或其他异常行为。
  2. 使用释放的内存:当DNS软件或系统尝试使用已经释放的内存时,可能导致程序崩溃或产生其他异常行为。
  3. 内存泄漏:DNS软件或系统中的内存泄漏漏洞可能导致系统内存资源被耗尽,从而影响系统的正常运行。
应对这些漏洞的方式
  1. 更新和配置DNS服务器:及时更新DNS服务器软件,并正确配置DNS服务器避免受到常见的DNS资源消耗攻击。
  2. 限制区域传送:对DNS服务器进行配置,限制对区域传送的请求,以防止遭受区域传送攻击。
  3. 安全监控:实施安全监控和日志记录,以及时发现和响应DNS资源消耗攻击行为。
  4. 使用防火墙和入侵检测系统:配置防火墙和入侵检测系统,以检测和阻止恶意的DNS流量。
  5. DNSSEC:部署DNSSEC(DNS安全扩展)来确保DNS数据的完整性和真实性,从而防范DNS缓存投毒攻击。
  6. 安全编程实践:在DNS软件或系统的开发过程中,采用安全编程实践,包括对用户输入进行正确的验证和过滤,以避免出现非内存崩溃漏洞。
  7. 代码审查:进行定期的代码审查,以发现和修复潜在的非内存崩溃漏洞。
  8. 安全测试:进行安全测试,包括静态代码分析和动态测试,以发现和修复潜在的漏洞。
  9. 及时修补:定期更新DNS软件和系统补丁,以修复已知的非内存崩溃漏洞。