一、基础概念
1.1 概念
域名系统(Domain Name System,DNS)是互联网的一项基础服务,默认端口53,可以实现域名和IP地址的相互映射,其数据库分散在全球的多地。
1.2 协议
DNS默认使用UDP协议通信,但是由于UDP的报文长度限制为512字节,当DNS请求超过此长度时会自动使用TCP协议发起请求。
1.3 域名层次
DNS(或者说域名)是划分层次的,它有根域(Root Doamin)、顶级域(Top Level Domain,TLD)、二级域(Second Level Domain,SLD)等级别,如下图以www.baidu.com介绍其层级,其中根域是一个点,只是默认情况下都不再输入了。通常我们说全球有13台根域名服务器,实际上是有13个根域名服务器地址,服务器数量有1000+,采用任播技术实现负载均衡。

比如访问:https://www.qq.com. ,但是有些域名后面加点是不行的,应该是服务端做了限制,比如https://www.baidu.com.
1.4 记录类型
DNS 中,常见的资源记录类型有:
-
NS (Name Server):指定解析域名或子域名的 DNS 服务器
-
MX(Mail Exchanger):指定接收信息的邮件服务器
-
A(Address):指定域名对应的 IPv4 地址记录
-
AAAA:指定域名对应的 IPv6 地址记录
-
CNAME(Canonical Name):一个域名映射到另一个域名或 CNAME 记录或映射到一个A记录
1.5 解析过程
域名解析是有顺序的,一般首先通过host 文件的静态解析,然后通过DNS 服务器的动态解析,静态解析的优先级高于动态解析。

解析的过程分为以下几步:
-
如果Host 文件没有这个DNS 解析记录,则会查找本地的DNS 缓存,如果有则直接使用此解析结果
-
如果本地缓存没有这个域名的解析记录,则会查找本地DNS服务器,如果有则直接使用此解析结果
-
如果本地DNS服务器没有这个域名的解析记录,但在缓存中发现了映射关系,则直接使用此解析结果,但此解析不具有权威性
-
如果本地机器和DNS服务器都没有此解析记录,本地DNS就会把请求发送至根域服务器,根域服务器会根据顶级域类型(.com)返回一个可以解析此类型的顶级域服务器地址;本地DNS服务器收到此地址后会向此顶级域地址发起请求,若顶级域服务器自己无法解析会返回一个二级域(baidu.com)服务器地址,本地DNS服务器会再次尝试请求,如此重复查询,直到找到解析结果或返回无法解析的错误信息
注:本地DNS服务器也可以说成递归解析器(Resolver),后面的根域、顶级域、二级域DNS服务器也可以统一说成权威域名服务器(Authoritative Name Server)。
二、DNS 劫持漏洞
2.1 漏洞原理
DNS劫持漏洞通常是由废弃的DNS记录造成的,废弃DNS 记录是指一个DNS指向的资源已经被释放掉了,但解析仍然存在,若其指向的资源可被第三方获取,则存在劫持风险。常见的几种解析记录类型都存在此风险,比如A、CNAME、MX、NS等,但其实有些场景很难利用,比如A记录的劫持需要能够获得目标站点的IP,这个是非常困难的。
比较常见的劫持是CNAME 记录劫持或 NS记录劫持,以NS记录劫持为例,在2020年CCS顶会的一篇文章《Zombie Awakening: Stealthy Hijacking of Active Domains through DNS Hosting Referral》中提出了一种僵尸激活攻击(Zombie Awakening),其利用条件有两点:
-
域名的二级域指向了一个DNS 托管服务(一个第三方的DNS解析服务,很多云厂商都会提供这个服务)
-
DNS 托管服务商未验证域名的归属(大多数厂商只会验证在自家注册的域名,实际也很难验证全部的域名)

漏洞场景如上图(其过程忽略了根域)所示,其过程是一个请求example.com 域名的DNS 解析过程,在ns.example.com 的二级域DNS服务器中存储了example.com 的NS记录和A记录。其中如下这条NS记录
example.com NS ns.provider.com
虽然仍然存在,但ns.provider.com 的服务提供商已经删除了此项配置(比如用户已经不在使用provider.com 的服务了)。此时,上面那条NS 记录就可以称之为僵尸记录或失效记录。

漏洞利用过程就是如上图所示,分为以下几个步骤:
example.com NS ns.provider.com example.com A IPattacker
然后刻意的发起大量NS解析请求(3),当本地DNS服务器没有此记录时会向顶级域服务器发起请求(4),顶级域服务器返回一个NS记录(5)
example.com NS ns.example.com
本地DNS服务器根据NS 记录进一步向二级域(ns.example.com)发起请求(6),此时本地DNS服务器会收到一个A记录和两条NS记录并缓存下来(7),在这个例子中此前从顶级域获得的NS记录会被从二级域获得的相同的记录替换掉,因为二级域比顶级域具有更高的优先级(8)。
然后攻击者向本地DNS服务器发起大量A记录解析请求(9),此时服务器中缓存了两个NS记录,一个真实的和一个废弃的,如果是随机选择的(10),则会有50%的机会返回攻击者的IP,那么那条废弃的解析路径就相当于被激活了(11)。而且这条A记录还会被缓存在递归解析服务器中,直到过期。攻击者可以尝试访问这个域名来判断攻击是否有效(13),若能够访问恶意IP则说明成功(14)。
2.2 漏洞测试
使用我自己的万网域名和某第三方的DNS托管服务,在原有万网DNS的基础上添加第三方的DNS地址。

NS记录成功解析后如下图所示

使用第三方DNS也可以返回正确的A记录

然后在第三方DNS服务商删除此域名,可以看到已无法获取A记录

然后使用另外一个第三方DNS服务商的账户添加域名并设置恶意的解析(A记录为127.0.0.1),然后使用dig命令指定外部DNS 服务器进行测试(本地的应该有了正确IP地址的缓存,可能无法复现)。如下图所示,使用不同的DNS 服务器,有几率返回不同的结果,其中就有恶意A记录。

2.3 漏洞修复
此类漏洞关键在于域名管理员要合理配置的域名解析记录,不再使用的要及时下掉!
三、DNS 拒绝服务
3.1 漏洞原理
DNS 拒绝服务比较常见的可能是利用DNS Flood,做流量放大攻击其他服务器,但本质不是DNS的漏洞。这里介绍一种最新的针对DNS 的拒绝服务攻击–NXNSAttack,是发表在2020年安全顶会USENIX上最新的一篇研究成果《NXNSAttack: Recursive DNS Inefficiencies and Vulnerabilities》。该文章提出一种新型的DNS 放大攻击,利用DNS 对NS记录完全解析的特性,可以实现多倍的流量放大,对DNS 服务器造成拒绝服务。
在1.5 节或者2.1 节我们可以看到一个完整的理论上的DNS解析过程,但实际上一个递归解析器与DNS服务器(顶级域、二级域等)的通信要远多于上图所示次数。一个真实DNS请求的如下图所示,当递归解析器向顶级域发起请求时(1)会得到一个NS 记录列表(2),然后会向每个NS记录发起请求(3-6),每个NS地址会返回对应的A记录和NS记录(7-10),此时递归解析器已经获取到了二级域的NS服务器IP地址,但同时也收到对应的NS记录,由于DNS解析的特性(会对NS记录进行完全的解析,即只要收到NS的响应就会发起NS请求)递归解析器会发起一次A记录请求,向二级域DNS问询NS地址的IP地址(11-14,16-19),最后询问主域名的IP(15)获得地址(20)。

利用这个特性,攻击者就可以实现DNS流量放大,达到拒绝服务的效果。漏洞利用需要具备两个条件:
-
可以发起DNS请求
-
拥有大量二级域NS记录
发起DNS 请求就不说了,二级域NS记录通过购买域名并自定义配置,很多域名服务商可以购买特别廉价的域名,使用较低的成本就可以获得大量的NS记录。如下图所示,当满足了上述两个条件,攻击者可以发起一个 sd1.attacker.com 的DNS 请求,请求会到达attacker.com 的威域DNS服务器并返回提前设置好的大量NS记录,这些NS记录指向的就是受害者二级域,此时攻击者的本地递归解析器会向victimc.om 的DNS服务器发起大量NS解析请求,其数量时NS记录总量的两倍,因为每个记录会发起IPv4和IPv6两次请求。
在这种攻击模式下递归解析器和目标二级域DNS服务器都承受了大量的流量(与请求的Client数量和NS记录数量有关),是双向的攻击。

3.2 漏洞修复
这类型漏洞需要修复DNS解析程序的逻辑,不再完全解析NS记录,而是设置上限K,最多解析K个。
四、DNS 域传送漏洞
4.1 漏洞原理
DNS区域传送(DNS zone transfer)指的是一台备用服务器使用来自主服务器的数据刷新自己的域(zone)数据库。这为运行中的DNS服务提供了一定的冗余度,其目的是为了防止主的域名服务器因意外故障变得不可用时影响到整个域名的解析。一般来说,DNS区域传送操作只在网络里真的有备用域名DNS服务器时才有必要用到,但许多DNS服务器却被错误地配置成只要有client发出请求,就会向对方提供一个zone数据库的详细信息,导致了漏洞的产生。
4.2 漏洞利用
DNS 域传送漏洞使用nslookup 或dig命令直接测试即可,以dig 为例,其中axfr 参数表示向DNS主服务器发起的更新请求,若服务器存在漏洞,则会回传解析数据。

4.3 漏洞修复
修改dns服务器的配置,设置允许域传送服务器的白名单,一般为/etc/named.conf文件,设置其中的allow-transfer参数
allow-transfer { localhost; 1.1.1.1; };
五、DNS 缓存中毒
5.1 漏洞原理
DNS 缓存中毒是向 DNS 缓存中输入错误解析记录,使得正常的 DNS 查询时返回错误响应并将用户定向到错误网站,DNS 缓存中毒也称为“DNS 欺骗”。具体方式是向 DNS 解析器发出请求,然后在 DNS 解析器查询域名服务器时伪造答复,使 DNS 缓存中毒。DNS 缓存中毒过程:

中毒的 DNS 缓存:

实际上DNS 缓存中毒攻击比较难以实现,首先DNS 请求必须是使用UDP 协议时才能伪造响应包,然后由于请求和响应的时间较短,必须连续多次的发送请求并不断伪造响应包才有可能输入少量的错误缓存。
5.2 漏洞修复
比较常见的一些方法:
-
UDP端口随机化,使得攻击者无法猜测通信端口,难以伪造数据包
-
减少DNS缓存时间,DNS缓存一但刷新此前的伪造就会失效
-
使用DNSSEC对DNS通信进行签名
六、DNSSEC
DNS安全扩展(Domain Name System Security Extensions,DNSSEC),是由IETF提供的一系列DNS安全认证的机制。它采用基于公共密钥加密的数字签名,从而增强 DNS 验证强度。DNSSEC 并非对 DNS 查询和响应本身进行加密签名,而是由数据所有者对 DNS 数据自身进行签名。
每一个 DNS 区均包含一个公私秘钥对,DNS 区所有者使用该区域的私钥对区域内的 DNS 数据进行签名,为这些数据生成数字签名。该区域的公钥则在区域内公开发布,供全体用户检索。凡在区域内查找数据的递归解析器,还必需检索区域公钥,从而使用公钥验证 DNS 数据的真实性。解析器确认检索到的 DNS 数据的数字签名是否有效。如果有效,证明 DNS 数据合法,则将 DNS 数据返回给用户。如果签名未通过验证,解析器会假设发生攻击,丢弃数据并向用户返回错误。因此,DNSSEC 相当于在 DNS 协议中新增了两项重要功能:
-
数据来源验证 – 解析器可以通过加密的方式验证收到的数据是否确实来自其认定的数据传送区域。
-
数据完整性保护 – 解析器可以确信,自区域所有者使用区域私钥初次进行数据签名以来,数据在传输过程中并未遭到修改。
很多域名服务商已经提供了DNSSEC的配置能力。
