Paranoid Penguin - DNS 缓存中毒,第一部分

作者:Mick Bauer

近期很少有互联网威胁能像安全研究员 Dan Kaminsky 在 2008 年发现的域名系统 (DNS) 协议中的基本缺陷那样产生如此大的影响,攻击者可以利用这些缺陷重定向甚至劫持多种类型的互联网交易。DNS 软件提供商的直接反应是发布软件补丁,使有问题的“DNS 缓存中毒”攻击更难以实施,这无疑有所帮助。

但是,最好的解决方案是使用 DNSSEC,这是一种 DNS 协议的安全版本,它使用通过公钥基础设施 (PKI) 验证的 x.509 数字证书来保护 DNS 数据免受欺骗。DNSSEC 正在缓慢但稳步地部署到关键的互联网基础设施中。

DNS 缓存中毒是什么意思,它如何影响您?您如何保护您的用户免受针对您组织名称服务器的攻击?在接下来的几个月中,我将深入探讨 DNS 缓存中毒和 DNSSEC,包括 DNS 查询应该如何工作、它们如何被破坏以及如何在一般和具体方面受到保护。

我不会尝试涵盖 所有 DNS 服务器安全方面的问题,就像我的书 Linux 服务器安全 第六章(参见资源)中那样。但是,有了接下来几个月的专栏文章,我希望您能够理解并能够防御缓存中毒,这是一种特殊但非常恶劣的 DNS 漏洞。

似乎是这些多期连载的模式,我将从一般、较少实践操作的层面开始,并随着系列的进展进入越来越技术性的细节层面。接下来,让我们讨论 DNS 应该如何工作以及它如何被破坏。

DNS 基础知识

域名系统既是一种协议,也是一种互联网基础设施,用于将用户友好的“名称”(例如,www.linuxjournal.com)与网络和计算机关联起来,而网络和计算机实际上通过它们的互联网协议 (IP) 地址(例如,76.74.252.198)相互了解并被网络基础设施设备所知。

听起来很简单,对吧?如果互联网不是由成千上万个不同的组织组成,每个组织都需要控制和管理自己的 IP 地址和命名空间,也许就会很简单。正因为如此,互联网的域名系统是一个分层但高度分布式的“名称权威”网络——也就是说,DNS 服务器仅对特定的命名空间区域具有“权威性”。

因此,将主机或网络/域名解析为 IP 地址,就是一个确定 哪个 名称权威知道您特定问题的答案的问题。而且,正如您很快就会看到的,您能够 信任 您最终收到的答案至关重要。如果您在 Web 浏览器中输入您银行的在线银行站点名称,您不希望被发送到 online.mybank.com 的巧妙克隆站点,该站点行为与真实站点完全一样,但具有将您的登录凭据发送给有组织犯罪集团的“额外功能”;您希望被发送到 真实 的 online.mybank.com。

因此,DNS 查找(也称为查询)中的安全挑战是确保攻击者无法篡改或替换 DNS 数据。不幸的是,DNS 协议在设计时没有严格的技术控制来防止此类攻击。

但是,我有点超前了!让我们剖析一个 DNS 查找,以展示当您在浏览器中键入 URL 到页面开始加载之间发生的事情。

您的 Web 浏览器实际上不与权威名称服务器交互。它将问题“online.mybank.com 的 IP 地址是什么?”传递给您计算机本地的“存根解析器”,这是操作系统的一部分。您的操作系统将查询转发到您本地网络的 DNS 服务器,该服务器的 IP 地址通常存储在 UNIX 和类 UNIX 系统上的 /etc/resolv.conf 文件中(尽管这通常只是存储在某些其他网络配置脚本或文件中的数据副本,或者是从 DHCP 服务器接收的配置数据)。

该本地名称服务器(实际上由您组织的信息技术部门或您的互联网服务提供商运行)然后执行以下两件事之一。如果它已经相当近地解析了 online.mybank.com,它会将查询结果从其最近解析名称的“缓存”中发送给您的浏览器。如果 online.mybank.com 不在其缓存中,它将代表您执行递归查询。

递归查询通常需要几个步骤,如图 1 所示。在我们的示例中,递归 DNS 服务器首先从本地存储的列表中随机选择一个互联网“根”名称服务器的 IP 地址(每个 DNS 服务器都有此列表;它不是很长,也很少更改)。它向该根名称服务器询问 online.mybank.com 的 IP 地址。

Paranoid Penguin - DNS Cache Poisoning, Part I

图 1. 递归 DNS 查询

根名称服务器回复说它不知道,但它将递归名称服务器引用到 .com 顶级域 (TLD) 的权威名称服务器——在我们的示例中,虚构主机 dotcom.au7h.com。根名称服务器还提供了该主机的 IP 地址 (3.30.30.31)。这两个记录,即引用 dotcom.au7h.com 作为 .com 权威机构的 NS 记录和提供 dotcom.au7h.com IP 地址的 A 记录,称为粘合记录。

然后,递归名称服务器询问 dotcom.au7h.com 是否 知道 online.mybank.com 的 IP 地址。它也回复说它不知道,但它将递归名称服务器引用到另一个名称服务器 ns.mybank.com,该服务器是 mybank.com 域的权威机构。它还提供了该主机的 IP 地址 (5.50.50.50)。

最后,递归名称服务器询问 ns.mybank.com 是否知道 online.mybank.com 的 IP 地址。是的,它知道:ns.mybank.com 回复请求的 IP 地址,递归名称服务器将该信息转发回最终用户的存根解析器,然后存根解析器将 IP 地址提供给最终用户的 Web 浏览器。

那么,在本例中,来自您的存根解析器的简单查询导致来自您的本地递归 DNS 服务器的三个查询,分别代表针对根、.com TLD 和最终 mybank.com 域名的查询。这三个查询的所有结果都由本地 DNS 服务器缓存,从而避免了您的服务器不断向 .com 和 mybank.com 的权威名称服务器发送请求,直到这些缓存条目过期。

该过期时间由每个缓存记录的生存时间 (TTL) 值决定,该值由提供给定记录的任何权威名称服务器指定。将 IP 映射到特定主机的 A 记录往往具有相对较短的 TTL,但指定整个域或 TLD 的权威名称服务器的 NS 记录往往具有较长的 TTL。

我已经描述了 DNS 查询递归应该如何工作。它如何被破坏呢?

DNS 缓存中毒

到现在为止,有两件事对您来说应该很明显。首先,DNS 是一项至关重要的互联网基础设施服务,它必须正常工作,用户才能访问他们希望与之交互的系统。其次,即使是针对单个 IP 地址的简单 DNS 查询也可能导致多次网络事务,其中任何一次都可能被篡改。

由于 DNS 事务在大多数查询和回复中依赖于“无状态”UDP 协议,因此 DNS 事务本身就容易受到篡改、数据包注入和欺骗。在本地级别篡改 DNS 查询的回复,就像向发出查询的“目标”系统发送欺骗数据包,并希望它们在查询的“真实”答案到达之前到达一样简单。

欺骗从递归 DNS 服务器发送到客户端系统的 DNS 回复只会影响该客户端系统的一个用户。如果您可以篡改递归名称服务器的查询,将虚假数据注入其缓存,从而影响使用该 DNS 服务器的 所有 计算机的 DNS 查询,那会怎么样?

而且,如果您不严格篡改描述单个主机 IP 的单个 A 记录,而是注入欺诈性 NS 记录,将 DNS 查询重定向到您的(欺诈性)名称服务器,从而可能影响整个域名,那会怎么样?

当安全研究员 Dan Kaminsky 在 2008 年发现 DNS 协议中的基本缺陷时,这些正是他确定的攻击场景。在您 过恐慌之前,我想先剧透一下,即使在 2008 年,在他就这些攻击进行了现已著名的 Black Hat 演示之前,Kaminsky 就与 ISC 和 Microsoft 等 DNS 服务器软件供应商合作,发布了紧急补丁,至少部分缓解了这种风险,然后 Kaminsky 的攻击才广为人知。

但是,攻击只是通过补丁部分缓解了。因为这是一个如此重要、广泛且有趣的问题,所以让我们深入探讨 Kaminsky 的 DNS 缓存中毒攻击。

图 1 中构成 DNS 查询的所有事务都使用 UDP,我已经说过 UDP 很容易被欺骗。那么,有什么可以阻止攻击者向这些事务中的任何一个发送欺诈性回复呢?

在 2008 年之前,这个问题的答案是双重的:查询 ID 和域内检查。每个 DNS 查询数据包都包含一个查询 ID,这是一个 16 位数字,必须包含在该查询的任何回复中。至少,查询 ID 可以帮助递归 DNS 服务器(可能同时有许多并发查询正在等待处理)将回复与其到达时的正确查询关联起来,但查询 ID 也应该使欺骗 DNS 回复更加困难。

域内(Bailiwick)在这里是“相关性”的同义词。DNS 回复中包含的任何粘合记录都必须与相应的查询相关。因此,如果攻击者试图通过“Kashpureff 攻击”(参见资源部分中对 Cricket Liu 的采访)来毒害递归 DNS 服务器的缓存,在这种攻击中,通过粘合记录将无关信息发送到已被诱骗向恶意名称服务器发出查询的递归 DNS 服务器,则只有当递归名称服务器未能执行将这些粘合记录与查询相关联的域内检查时,攻击才会成功。

例如,如果我可以让递归 DNS 服务器查找名称 an.evilserver.com,并且我控制了 evilserver.com 域名,我可以发送一个回复,其中不仅包含请求的 IP,还包含“额外”的 A 记录,这些记录指向 www.citibank.com、www.ameritrade.com 和其他我希望使用冒名顶替服务器拦截其流量的站点。

这些伪造的 A 记录将 替换 目标递归名称服务器已缓存的任何这些主机的记录。但是,自 1997 年以来,域内检查一直是几乎所有 DNS 服务器软件的标准默认功能,因此 Kashpureff 攻击在很大程度上已经过时了(就任何历史 TCP/IP 攻击而言)。

因此,回顾一下,查询 ID 应该可以防止回复欺骗,而域内检查应该可以防止粘合记录出现异常。

然而,Kaminsky 发现,尽管有查询 ID 和域内检查,但仍然有可能 欺骗 DNS 回复,又滥用粘合记录,从而成功地毒害大多数递归名称服务器的缓存。以下是 Kaminsky 攻击的工作原理。

此攻击的目的是用欺诈性 A 记录(针对单个主机)甚至欺诈性 NS 记录(针对整个域名)来毒害递归 DNS 名称服务器的缓存。在我即将使用的示例中,目标是注入主机 online.mybank.com 的欺诈性 A 记录。

这将通过发起或诱骗递归名称服务器服务的某些其他主机发起针对随机的、假定的不存在的主机名的洪水查询来实现,这些主机名与我们希望劫持的主机名位于同一域名中。图 2 显示了攻击者发送针对主机名的洪水查询,例如 random3232.mybank.com、random4232.mybank.com 等等。

Paranoid Penguin - DNS Cache Poisoning, Part I

图 2. Kaminsky 的缓存中毒攻击

除了生成大量查询很方便之外,查询随机/不存在的主机名还增加了答案尚未缓存的几率。显然,如果您发送一个查询,请求某个 IP 已经在递归名称服务器缓存中的主机,则该名称服务器会将有问题的 IP 发送给您,而无需进行任何递归查询。没有递归查询,就没有名称服务器回复可以欺骗!

几乎与发送查询同时,攻击者释放洪水般的欺骗回复,声称来自该域名的权威名称服务器(在图 2 中为 ns.mybank.com)。关于这些回复,有几点值得注意。

首先,如图 2 所示,它们 提供对攻击者查询的答案,因为您知道这些查询无论如何都与不存在的主机有关。相反,它们将递归名称服务器引用到另一个“名称服务器”online.mybank.com,并方便地提供其 IP 地址(当然,实际上是攻击者控制的系统的 IP 地址)。

这些查询的重点是提供一个机会来发送 通过域内检查但仍然是欺诈性的粘合记录。如果您试图劫持整个域的 DNS,在这种情况下,您将欺骗对顶级域权威机构(例如 .com)的查询的回复,您将发送指向恶意 DNS 服务器的粘合记录,该服务器可以例如,为流行的在线银行和电子商务站点发送欺诈性(攻击者控制的)IP,并简单地递归其他所有内容。

但是,在此示例中,攻击者改为使用 假装 引用不同的名称服务器,以便将伪造的 online.mybank.com Web 服务器的 IP 地址植入目标递归名称服务器的缓存中。这个伪造的 Web 服务器甚至不响应 DNS 查询这一事实并不重要;攻击者希望在线银行流量流向那里。

关于攻击者的欺骗回复的第二个值得注意的事情(这 在图 2 中显示)是,每个回复都包含不同的随机查询 ID。发送洪水般的查询和洪水般的回复的原因是最大化这些回复的查询 ID 之一与目标递归名称服务器已发起到 ns.mybank.com 的相应递归查询之一的查询 ID 相匹配的机会。

而且,这可以说是 Kaminsky 攻击最重要的方面。通过同时多次猜测多个查询的查询 ID,攻击利用“生日问题”来提高将欺骗回复与真实查询匹配的机会。我将克制住在这里描述生日问题的诱惑(参见资源),但足以说明,这是一个统计学原理,它指出,对于任何潜在的共享特征,即使稍微增加受试者的人口,两个或多个受试者共享该特征的几率也会显着增加。

因此,即使攻击者猜测单个 DNS 查询的正确查询 ID 的几率是 65,534 比 1,但如果攻击者尝试多个查询,每个查询都有多个伪造回复,则这些几率会呈指数级提高。事实上,使用脚本化攻击,Kaminsky 报告在短短十秒钟内就取得了成功!

图 2 中未显示的另一件事是攻击者的欺骗回复中欺诈性粘合 A 记录的 TTL。攻击者会将此 TTL 设置得非常高,以便如果攻击成功,受害者名称服务器会将欺诈性 A 记录在其缓存中保留尽可能长的时间。

关于此攻击需要注意的最后一件事是,如果在 ns.mybank.com 设法将其真实回复返回给递归名称服务器之前,没有一个欺骗回复与查询匹配,则此攻击将失败。再次强调,发起大量同时查询会增加赢得至少一场与真实名称服务器的竞争的几率,回复中包含有效的查询 ID。

缓解 Kaminsky 的攻击

尽管 Dan Kaminsky 的缓存中毒攻击令人恐惧,但短期修复很简单:使 DNS 服务器软件从随机 UDP 源端口发送其 DNS 查询,而不是使用 UDP 端口 53 或其他静态、可预测的端口。在 2008 年之前,BIND、Microsoft DNS Server 和其他 DNS 服务器软件包会从单个端口发送所有 DNS 查询。这意味着要欺骗 DNS 查询的回复,攻击者只需要知道目标服务器正在运行哪种类型的 DNS 软件,才能知道要用作欺骗回复数据包的目标端口的 UDP 端口。

因此,随机化查询源端口使欺骗者的工作变得更加困难:他们要么必须窃听网络流量并观察给定查询的来源端口,要么向许多不同的端口发送大量欺骗回复,希望其中一个端口正在“侦听”回复。因此,在 Kaminsky 的缓存中毒攻击的背景下,从甚至小到 2,048 个可能端口的池中选择随机源端口,使攻击者猜测有效 DNS 回复数据包应该是什么样子的难度,比他们只需要猜测正确的查询 ID 时高出整整 2,048 倍!

果然,在 Kaminsky 公开宣布其攻击细节之前,他说服 DNS 服务器软件供应商发布补丁,使其各自的产品随机化 DNS 查询源端口,现在在 2011 年,这是 DNS 服务器默认的行为方式。然而,这只是部分修复。仍然有可能使 Kaminsky 的攻击奏效;只是需要更长的时间。

更好的修复方法是对 DNS 区域数据进行加密签名,以便递归名称服务器可以验证 DNS 回复。这可以通过 DNS 协议的 DNSSEC 扩展来实现,DNSSEC 将成为接下来一两篇专栏文章的主题。

结论

在详细描述了 DNS 递归和缓存中毒攻击之后,下次,我将开始向您展示如何在您自己的(基于 BIND 的)递归名称服务器上启用 DNSSEC,以便它检查它遇到的任何签名 DNS 数据的签名。在那之前,请确保您的 DNS 软件已完全修补,尽量不要 过担心,并注意安全!

资源

Linux 服务器安全,第二版,作者:Mick Bauer,Sebastopol, CA: O'Reilly Media, 2006。

“Kaminsky DNS 漏洞图解指南”,作者:Steve Friedl,Unixwiz.net 技术提示:unixwiz.net/techtips/iguide-kaminsky-dns-vuln.html

“DNS 漏洞:对 Cricket Liu 的独家采访”,作者:Greg Ness,Archimedius: gregness.wordpress.com/2008/07/23/dns-vulnerability-an-exclusive-interview-with-cricket-liu

生日问题:en.wikipedia.org/wiki/Birthday_paradox

“理解 Kaminsky 的 DNS Bug”,作者:Cory Wright:www.linuxjournal.com/content/understanding-kaminskys-dns-bug

Mick Bauer (darth.elmo@wiremonkeys.org) 是美国最大的银行之一的网络安全架构师。他是 O'Reilly 图书 Linux 服务器安全 第二版(以前称为 使用 Linux 构建安全服务器)的作者,偶尔在信息安全会议上发表演讲,也是“网络工程波尔卡舞曲”的作曲家。

加载 Disqus 评论