DNS 安全(二):针对 DNS 协议的攻击

本来以为 2 篇就能说完,后来发现内容还是挺多的,所以我拆成了 3 篇,本篇是第 2 篇:“针对 DNS 协议的攻与防”,下一篇是“利用 DNS 的攻与防”。

前置知识

在阅读本文之前,强烈建议你先看上一篇。这里补一些上一篇遗漏的知识点。

DNS 发展历史

最近看了一篇文章:http://suo.im/6b7UFl 。总结的很不错,主要是发展历史,我这里摘抄一下:

“我们可以简单总结一下 DNS 的发展史,1987 年的 RFC1034 和 RFC1035 定义了最初版本的 DNS 协议,刚被设计出来的 DNS 就会同时使用 UDP 和 TCP 协议,对于绝大多数的 DNS 查询来说都会使用 UDP 数据报进行传输,TCP 协议只会在区域传输的场景中使用,其中 UDP 数据包只会传输最大 512 字节的数据,多余的会被截断;两年后发布的 RFC1123 预测了 DNS 记录中存储的数据会越来越多,同时也第一次显式的指出了发现 UDP 包被截断时应该通过 TCP 协议重试。过了将近 20 年的时间,由于互联网的发展,人们发现 IPv4 已经不够分配了,所以引入了更长的 IPv6,DNS 也在 2003 年发布的 RFC3596 中进行了协议上的支持;随后发布的 RFC5011(DNSSEC)和 RFC6376(DKIM)增加了在鉴权和安全方面的支持,但是也带来了较长的 DNS 记录,UDP 数据包被截断变得非常常见。RFC6891 提供的 DNS 扩展机制能够帮助我们在一定程度上解决大数据包被截断的问题,减少了使用 TCP 协议进行重试的需要,但是由于最大传输单元的限制,这并不能解决所有问题。DNS 出现之后的 30 多年,RFC7766 才终于提出了使用 TCP 协议作为主要协议来解决 UDP 无法解决的问题,TCP 协议也不再只是一种重试时使用的机制,随后出现的 DNS over TLS 和 DNS over HTTPS 也都是对 DNS 协议的一种补充。”

真是长路漫漫啊。

any 类型的查询

ANY 我感觉算是 DNS 的“语法糖”。ANY 不是查询单个类型的记录(例如 A 或 MX),而是返回所有类型的记录,所以 ANY 查询的回复是 DNS 服务器对这个域名所能提供的最大的回复(域传送就不算了,它一般都需要授权)。

DNS 使用双协议:TCP 与 UDP

超过 UDP 限制的 DNS 数据会转为 TCP 来传输,所以 DNS 既会使用 UDP,也会使用 TCP。例子:

可以看到,如果响应数据包太大,DNS 服务器会返回不含 answer 的响应包,并且 tc 位是 1,即图中的 Truncated: Message is truncated,表明这个数据超长而有删节。dig 一看响应,就会使用 TCP 重发 request。当然如果 DNS 服务器不支持这样转 TCP 的方式,就没法传输大量的数据了。

DNS 缓存分布

来源于网图:http://suo.im/6b7rft

DNS 错误响应分布

来源于网图:http://suo.im/63JBWU

EDNS

扩展 DNS 机制(Extension Mechanisms for DNS),就是在遵循已有的 DNS 消息格式的基础上增加一些字段,来支持更多类型的 DNS 请求业务。RFC2671 指出了 EDNS 被提出来的几个理由:

  1. DNS 协议头部的第二个 16 字节中都已经被用的差不多了,需要添加新的返回类型(RCODE)和标记(FLAGS)来支持其他需求
  2. 只为标示 domain 类型的标签分配了两位,现在已经用掉了两位(00 标示字符串类型,11 表示压缩类型),后面如果有更多的标签类型则无法支持,建议用上 10 和 01
  3. 当初 DNS 协议中设计的用 UDP 包传输时 DNS 数据大小限制为 512 字节,现在很多主机已经具备重组大数据包的能力,所以要有一种机制来允许 DNS 请求方通知 DNS 服务器让其返回大一些的数据包;

下面会看到,DNSSEC、edns-client-subnet 等都需要有 EDNS 的支持。但是直接更改协议是不可能的,没法保证全球的 DNS 以及设备都能同时更新,所以 EDNS 中引入了一种新的伪资源记录 OPT(Resource Record),之所以叫做伪资源记录是因为它不包含任何 DNS 数据,OPT RR 不能被 cache、不能被转发、不能被存储在 zone 文件中。OPT 被放在 DNS 通信双方 DNS 数据包的 ADDITIONAL SECTION 中,每个 DNS 数据包中只能有一个 OPT 伪资源记录。对于我们搞安全的来说,比较重要的是第 3 点,即 UDP payload size。它可以告诉 DNS 服务器,请求方够处理的最大 UDP 报文的大小(没事我还扛得住,你尽管来)。用 dig 的时候它都会自己带上这个 bufsize,默认大小是 4096,我们可以指定这个大小:dig @8.8.8.8 github.com any +bufsize=6666,当然我们也可以将 bufsize 设置的小一些,强迫 DNS 服务器使用 TCP 传输。大家可以自行对比一下:dig @8.8.8.8 github.com anydig @8.8.8.8 github.com any +bufsize=1

有些比较有意思的现象:

  1. 我遇到的 DNS 服务器都只有在响应数据 >= 512(看服务器设定的大小)的时候才会按照 bufsize 去走 TCP,比如你要是 dig @8.8.8.8 github.com +bufsize=1,来强迫使用 TCP 协议是没用的。
  2. 有些 DNS 服务器当 bufsize 设置的很大的时候,只会返回必要的数据,但是如果返回的数据超过设定的 bufsize,就会走 TCP 返回所有的数据。因为这个时候已经没有被拿去放大的风险了。大家可以自行摸索一下执行 dig @dns-1.datamerica.com defcon.org RRSIG +bufsize=593dig @dns-1.datamerica.com defcon.org RRSIG +bufsize=592 返回数据的不同。
  3. 结合上面 2 条,若 DNS 服务器发现删除 ADDITIONAL SECTION 之后小于指定的字节,则不会走 TCP,而是返回删除 ADDITIONAL SECTION 之后的响应。

上述行为我没去 rfc 里确认,实在啃不动了。。。我就当做 DNS 服务器(组件)的共同特性好了。

最后,如果服务器不支持 EDNS,那么就会返回 RCODE NOTIMPLFORMERR 或者 SERVFAIL,可以参考上面的那个错误分布图。rfc 明确指出了这一点:

edns-client-subnet

这个是与 CDN 有关的,能够更加方便与快捷地加速内容传输,与本文关系不是很大,所以简单提一下。edns-client-subnet 的详细格式存在 EDNS 的 RDATA 中,例如 1.1.1.1 当 localDNS 递归向 CDN 服务厂家 DNS 查询的时候,会带上用户出口的 ip(1.1.1.1)地址,DNS 服务器会根据用户出口 ip 地址归属,返回对应 CDN 接入点最近的 ip 地址。

DNSSEC

DNSSEC(Domain Name System Security Extensions),DNS 安全扩展。

流程基本上没变,只是权威服务器返回的响应的时候回附带 type 是 RRSIG(Resource Record Signature)的 RR。客户端在拿到之后发现有 RRSIG,若选择验证,则需要继续走下面的几个步骤。

简单地来说就在 DNS 上加了数字证书。RRSIG 记录正如上面所讲的,就是 DNS 权威服务器对这个解析结果的一个数字签名。DNS 权威服务器有自己对应的私钥(ZSK),它的作用就是用来对 DNS 请求结果进行数字签名生成数字摘要,然后原先的记录以及这条信息摘要就会一同发送给我们。有了签名之后,我们就接着通过请求 DNSKEY 记录来获取对应的公开密钥。拿到了公开密钥之后,我们可以用它先来解密 RRSIG 的摘要,然后我们利用相同的散列算法再算一次摘要,然后之前拿到的 RRSIG 中的摘要和自己算出来的摘要进行比对,如果相同的话就说明这次查询结果是可信的。

那么问题来了,我们初中的时候就知道数字签名是没法抵御中间人攻击的,原因在于我们没法验证公钥是否是可信的。在 DNSSEC 场景下,就是如果攻击者把 RRSIG 以及 DNSKEY 记录都劫持了,该怎么办呢?对于验证证书这个问题,HTTPS 的解决方案是 CA,DNSSEC 的解决方案是 KSK。

DS (Delegation Signer) ,DS 的值是用域名(例如 baidu.com)的上一级(com)的私钥(KSK)对 baidu.com 的 DNSKEY 进行加密之后得到的。如果你不信任 baidu.com 的 DNSKEY,可以拿 com 的公钥进行解密、计算、比对,这样就可以验证 DNSKEY 是不是真实的。如果你连 com 的记录都不信的话,可以在去上根域名验证,通过类似的方法,比对 com 的记录是否正确。那么问题是根域名要怎么验证呢?这个需要手动存在本地,也就是说如果写的客户端,想要用 DESSEC 保护自己的 DNS 查询,那么就需要自行存一份。附上一份参考资料:http://suo.im/5sP2RT

可惜现在部署 DNSSEC 的网站还是太少了,早期的 chrome 支持过 DNSSEC 的验证流程,后面也下掉了。并且 DNSSEC 是没法保护隐私的,也就是说任何能监视你网络流量的人,也可以看到你通过 DNSSEC 查询了哪些域名。

DoT 与 DoH

DoT 即 DNS over TLS,DoH 即 DNS over HTTPS。显然,DoT 比 DoH 少了一层,所以速度更快;但是 DNS 缓存机制,基于这两个协议设计的 DNS 也可以有缓存机制,所以我认为两者在速度上的差别可以忽略。并且对于客户端来说,用 HTTPS 是最方便的,不管是浏览器还是编程语言的库。所以我感觉 DoH 要比 DoT 有希望。

举个 DoH 的例子吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# macr0phag3 in ~ [11:55:41]
» curl -s -H 'accept: application/dns-json' 'https://cloudflare-dns.com/dns-query?name=baidu.com&type=A' | jq
{
"Status": 0,
"TC": false,
"RD": true,
"RA": true,
"AD": false,
"CD": false,
"Question": [
{
"name": "baidu.com",
"type": 1
}
],
"Answer": [
{
"name": "baidu.com",
"type": 1,
"TTL": 375,
"data": "220.181.38.148"
},
{
"name": "baidu.com",
"type": 1,
"TTL": 375,
"data": "39.156.69.79"
}
]
}

用起来是不是比想象的简单呢?现在 Chrome 与 Firefox 也都支持了 DoH,但是需要手动打开,感兴趣的话可以自行体验。

那么在上面的例子中,攻击者能不能通过劫持 cloudflare-dns.com 的 DNS 解析,进而劫持待查询的域名呢?这个问题本质上是,https 能否被劫持,这个问题回答起来不难但是比较有趣,所以我就留给各位自己思考了。

DNS 泛解析

DNS 泛解析很好理解,就是将*.域名解析到同一 IP,这样方便管理,同时相当于创造了无数个可以访问的二级域名,对用户比较友好。

但是居然有些 TLD 都存在泛解析,非常不可思议,因为顶级域的管理应该非常严格。至少 wsph 这 2 个 ccTLD 是开启泛解析的,随便挑选在它们下面的顶级域名,都可以解析出 IP 并且往往是同一个。比如 xm91iplj6tugqkf.wsuOwnucwMkuiqpSJ.ws 这些随机域名的 IP 都是 64.70.19.203;对应的 ph,这些随机域名的 IP 地址都是 45.79.222.138。这一行为会对安全分析带来严重的影响,可能会导致误判,一个典型的例子比如银行木马 dyre 的 DGA 域名有的是以 ws 作为 TLD,显然它们都会有有效的解析地址,但并不是真正的 C&C 地址(对于 DGA 的介绍会在第三篇里出现,这句话不理解可以先跳过)。

不过目前不是很清楚 ICANN 为啥没有限制这个行为,感觉有什么 py 交易。。。

针对 DNS 协议的攻与防

服务器/客户端被入侵/控制

  1. 针对 DNS 服务器:攻击者如果挖到 DNS 组件的 0day,比如 bind,从而控制了 DNS 服务器,可以修改各种解析记录,这个危害是最大的,会影响大量的用户。以及 DNS 组件的一些漏洞,可能会被用于发起 DDoS,例如 CVE-2020-8616。
  2. 针对使用 DNS 的“客户端”(可能是客户端或者服务器,即发起 DNS 查询的主机):攻击者成功控制“客户端”之后,可以篡改 hosts,修改各种解析记录,但由于危害限定在单台机器上,所以影响一般没有第一点大。

第一点其实没啥好说的。第二点举个例子,比如,前几年频繁出现的家用路由器被 csrf 攻击。需要一个前提就是路由器提供修改 dns 配置的 web 接口(条件和常规的 csrf 一样,就不多说了),举个例子(为了看得方便加了换行):

1
2
3
4
5
6
7
8
9
10
http://admin:[email protected]/userRpm/LanDhcpServerRpm.htm
?dhcpserver=1
&ip1=192.168.1.100
&ip2=192.168.1.199
&Lease=120
&gateway=0.0.0.0
&domain=
&dnsserver=106.187.36.85
&dnsserver2=8.8.8.8
&Save=%B1%A3+%B4%E6

主要目的就是把 dns 服务器换成 106.187.36.85,为了确保所有访问都没有问题,再加入了 google 的 dns,当 106.187.36.85 有不能解析的域名时,去 8.8.8.8 获取地址,潜伏得会隐蔽一些。只要哪个人用的是这个接口的路由器,位于登录态或者是弱密码,访问了攻击者控制的域名,他的 DNS 就会被攻击者劫持。

至于防护嘛,其实没啥好说的,就是那些常规的东西。

DNS 欺骗/劫持/Sinkhole/钓鱼与缓存投毒

这几个其实原理是一致的,利用 DNS 协议认证的缺陷(查询请求的 ip、端口、随机的查询 id 是否一致),只不过侧重点稍有不一样,非要区分的话,缓存投毒与前三者的攻击目标不同:

所谓的 “欺骗/劫持/钓鱼”,可以针对客户端也可以针对 localDNS,而 缓存投毒 一般是针对 localDNS。

我们小学六年级就知道,DNS 响应是先到则先被接收。如果攻击者能够在 DNS 服务器与攻击目标之间插入一个恶意的节点,就能抢先在 DNS 服务器回复之前发送恶意的 DNS 响应给攻击目标,真正的响应由于在时间上晚于攻击者,所以直接被攻击目标舍弃。举个例子,攻击目标尝试解析 www.baidu.com,正常情况下 A 记录应该是 112.80.248.76,但是攻击者可以将 A 记录为 1.1.1.1(攻击者的服务器 ip) 的响应发给攻击目标,而这个时候真正的 DNS 响应说不定还在路上呢。成功欺骗之后攻击者就可以劫持攻击目标与 www.baidu.com 之间所有的通信流量,可以监听也可以钓鱼等等。那么显然,攻击者需要能够及时响应 DNS 查询请求。若目标位于内网,可以很方便地使用 arp 欺骗;如果要劫持位于公网的 DNS 服务器,最最最著名的例子嘛,就是 G!F!W 了...嗯,这也是为什么有些网站是无法直接访问的,可以通过修改 hosts 来科!学!上!网,也可以修改 hosts 来屏蔽广告,甚至是破解软件。对于企业来说,也可以用来对员工、服务器进行上网行为控制。由于我!国!国!情,各位可以看一下这个文章:http://suo.im/5HROq3

运营商技术还是很强的,能做的事情也比较多,至于有没有做嘛,各位自行判断吧。至少运营商(通信商或者卖域名的注册商)对于哪些不存在的域名,有时候会返回自己控制的 IP 以达到导流的目的(宣传域名注册啦或者黄页啦),这种行为并不仅仅发生在国内,在全世界各地都存在这种“劫持”行为,以至于 Chrome(以及基于 Chrome 内核的其他浏览器)在启动的时候要发送随机 DNS 查询对这种“劫持”行为进行探测以免干扰浏览器的正常工作(参考:Chrome 随机域名查询);上面提到的泛解析实际上也算劫持的一种,嗯,“大面积官方劫持”;再比如我有一次发现用 4G 访问我的博客会出现广告。。。其他的就不多说了,我们还是回到技术上来。

因为 DNS 协议有缓存的特性,所以一份恶意的 DNS 记录会被 localDNS 缓存下来,导致缓存被投毒,也就是说即使攻击者撤掉了恶意节点,这个劫持依旧会维持一段时间,直到 ttl 超时,缓存到期失效。那么显然,攻击者只能在 localDNS 的 DNS 缓存失效之后才能投毒成功,这样攻击效率就比较低,并且大家可能会以为,DNS 劫持一次只能劫持一个域名,其实可以劫持其一级域 ns 所管辖的所有域名。

2008 年的夏天,Dan Kaminsky 提出了新型 DNS 缓存投毒攻击:例如 baidu.com,攻击者随机生成一个 localDNS 不存在的子域名,a21m2u2ed0.baidu.com,向 localDNS 查询这个域名,这个时候 localDNS 就得去走 DNS 查询的完整流程。既然查询已经发出了,攻击就完成了一半,接下来伪造 baidu.com 的权威 DNS 应答数据包即可。攻击者可以在响应包的 AUTHORITY SECTION 中里加入自己控制的 ns,例如 baidu.com 的 ns 记录为 ns.tr0y.wang(攻击者的 DNS 服务器 ip),localDNS 的缓存被投毒成功之后,客户端对 baidu.com ns 所管辖的所有域名的查询都将被发送到攻击者的 DNS 服务器上。当然,这个恶意的中间节点不一定要位于 localDNS 与 DNS 权威服务器之间,与 localDNS 位于一个内网都可以对吧?只要能发送伪造的响应给 localDNS 就行,因为对随机域名的查询是由我们触发的。实施这个攻击还有个细节,如果劫持失败,正常流程下,比如 a21m2u2ed0.baidu.com 在 baidu.com 的 DNS 权威服务器中肯定是不存在的,所以 baidu.com 的 DNS 权威服务器应该返回包含 NXDOMIAN(代表域名不存在)的响应包,而 DNS 是有缓存否定答案机制的,TTL 从同一个响应的 SOA 记录中获取,也就是说,如果在不断暴力尝试 dns id 的过程中,发现向 localDNS 查询 a21m2u2ed0.baidu.com 结果是 NXDOMIAN,那么这个域名就没必要继续尝试了,需要更换下一个随机域名继续尝试。

这里顺便提一个问题,大家判断一下这个思路可不可行:

在 Kaminsky 攻击中,可以用 cname 去劫持其他域名吗?思路如下:A 为恶意节点,C 为 localDNS,A 向 C 发起 a21m2u2ed0.baidu.com 查询,并抢先在 DNS 权威服务器之前返回数据包,其中 2 条记录:1. cname 是 www.baidu.com;2. www.baidu.com 的 A 记录是 1.1.1.1。那么请问,www.baidu.com 是否会被 localDNS 缓存下来,ip 是 1.1.1.1?显然,如果这个方法可行的话,可以劫持非一级域下的任意域名,只要你 cname 到其他人的域名,再给出 A 记录即可。我手边没有 localDNS,要去验证稍有些麻烦,所以我拿 windows 测试了一下,因为客户端、os、localDNS 都会有缓存,可以再看一遍上面那个缓存分布图。为什么要选 Windows 呢?因为我没找到 Linux 和 macos 怎么查看 DNS 缓存...测试结果如下:
首先清空缓存:ipconfig /flushdns,然后访问一下百度:curl www.baidu.com(注意,这里如果用 dig 或者 nslookup 无法触发 win 的 dns 缓存机制,原因未知),然后用 ipconfig /displaydns 查看一下 www.baidu.com 的缓存:

在这同一级别下面确实可以看见 www.a.shifen.com 的 A 记录,但是这个时候是找不到单独列出的 www.a.shifen.com 缓存的,只有我执行了 curl www.a.shifen.com 之后,才能找到单独列出的缓存:

按照上面的思路,如果可行,在 curl www.baidu.com 结束之后应该就能找到单独列出的www.a.shifen.com 的 A 记录,实验证明此思路至少对 windows 的 dns 缓存机制是不可行的。

最后,攻击者如果没法控制整个通信过程,那么一般是通过猜测 dns id 来进行劫持。所以也会有相应的“补丁”方案,接收响应的组件可以做以下几件事情:

  1. 检查 DNS 的随机 id 是否匹配,id 是 2 位的 hex,也就是 32 位的随机量。
  2. 随机化源端口,也是 32 位的随机量,这个其实一般都满足,不过我看 bind 的配置可以固定源端口,不要这么做,攻击者只要抓个包就知道你的端口了。
  3. 查询域名的时候,随机化域名的大小写,这个可以增加很多的随机量。例如查询 www.baidu.com 的时候,查 www.baidu.cOm。由于域名不分大小写,所以权威 DNS 服务器依旧是查 www.baidu.com,虽然返回的 Answer 里也是小写,但是返回的数据包会附上 Query,里面与查询的 Query 是一样的:

那么对比一下响应中的 Query 的域名,与自己调整的域名是否一致就知道有没有被劫持了。最后还有一个现象,如果真的被劫持了,那么查询某个域名总是会出现 2 个应答甚至是多个应答(不同端口不同 id)。

当然这些都是比较简单的手段,比较好的办法是上面提到的 DNSSEC,不过我感觉 DNSSEC 快凉了。。。。但是我们还可以选择 DNS-over-TLS、DNS-over-HTTPS,虽然要走的路还有很长。

不过,各位不要以为保护隐私或者加密通信总是好事,正常的通信可以收到保护,那么恶意的通信同样可以通过这些办法得到保护,现在 NIDS 检测恶意域名解析是很简单的,直接拆 DNS 数据包看就完事了,如果恶意软件也上了 DoH,检测就变得很麻烦了。

至于 Sinkhole 嘛,其实改 hosts 文件就是一个利用小型的 Sinkhole 的例子,通过 DNS 劫持完成安全防护,我比较喜欢把它称为 DNS 黑洞。由于现在很多恶意软件常用域名进行通信,那么安全厂商或者防御者可以把这个域名的解析接管了(与 DNS 服务商合作或者是 localDNS 上面配置),把域名解析记录改为一个无害的地址,这样恶意软件的通信就被阻断掉了。那么显然,DNS 服务器所在的层级越高,得到保护的主机就会越多,所以有些安全厂商通过合作,把僵尸网络通信的域名劫持到自己的服务器上,这样就能够利用 Sinkhole 关闭一些大型的僵尸网络,顺便还可以研究一下僵尸网络的行为(毕竟通信 ip 用的是安全厂商自己的,数据都可以拿到了)。一个非常著名的例子就是 WannaCry,内置了一个域名:iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea.com,在感染过程中,它会首先尝试访问这个域名的网页,如果成功访问网页则退出,不会进一步执行;如果访问网页失败,则会继续运行,弹框勒索赎金。如果你对 WannaCry Sinkhole 的数据分析感兴趣,可以看一下 360 的这篇文章

如今,大多数的 DGA 域名都已经被不同的安全机构做了 Sinkhole,所以如果你发现 NIDS 里发出的告警,恶意域名的 ip 是 Sinkhole,那么说明这个恶意软件基本上已经被研究透彻了。当然,防御者可以查,攻击者自然也可以查,所以各家安全研究机构出于保护自身的 Sinkhole 的目的,一般也不会公开 Sinkhole 列表,所以业界尚未有完整的 Sinkhole 源。不过的确有安全研究机构做了一些整理,比如 abuse.ch 的 sinkdb

DDoS 攻击

DDoS 相关的知识后面有专门的系列会讲,所以这里就简单提一下 2 大类

(注意,这两类有重合的地方,第一类我就限定为在请求数据包与响应数据包大小差不多的情况下)

  1. 直接向目标 DNS 服务器发起大量查询

比如攻击者可以生成随机的子域名去逼 localDNS 不断进行递归查询或者查那些不存在的域名(这种攻击方式被称为 “DNS 散列前缀攻击”),尝试将服务器的 DNS 缓存填满;或者选择响应内容较多的域名,直接向权威 DNS 服务器查询,消耗服务器的性能。但是这种情况比较少,主要还是在攻击成本上,DNS 服务器本身就能够承受大量的流量(比如像 DNS 根服务器),基本上不会出啥问题,毕竟攻击者发起比全球设备更多的查询量成本太高了(实际上现在也没有这样 D 别人的吧...)。

  1. 放大型 DDoS 攻击

其实 DNS DDoS 一般都是这种情况,因为在默认情况下,随便一个小小的查询,DNS 服务器就会回复一个很大的数据包,攻击者便可以利用这个放大的特性来消耗 DNS 服务器的带宽与性能,也可以伪造源 ip 来 D 其他服务器。例如简单的 dig @目标ip . ns 或者利用 scapy 发送 b"\x51\x84\x00\x10\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01",仅仅 17 bytes,服务器就会回复 492 bytes 的内容,即放大 28 倍(使用 dig 的话放大比会小一些,因为 dig 发出请求的时候它自己会多附带一些东西,用 scapy 发出的请求数据包是最小的,所以放大比就是最大的):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# macr0phag3 in ~ [18:44:30]
» dig @x.x.x.x . ns
...
...

;; QUESTION SECTION:
;. IN NS

;; ANSWER SECTION:
. 420390 IN NS c.root-servers.net.
. 420390 IN NS b.root-servers.net.
. 420390 IN NS l.root-servers.net.
. 420390 IN NS a.root-servers.net.
. 420390 IN NS g.root-servers.net.
. 420390 IN NS k.root-servers.net.
. 420390 IN NS m.root-servers.net.
. 420390 IN NS d.root-servers.net.
. 420390 IN NS h.root-servers.net.
. 420390 IN NS e.root-servers.net.
. 420390 IN NS f.root-servers.net.
. 420390 IN NS i.root-servers.net.
. 420390 IN NS j.root-servers.net.

;; ADDITIONAL SECTION:
a.root-servers.net. 78399 IN A 198.41.0.4
b.root-servers.net. 78731 IN A 199.9.14.201
c.root-servers.net. 78702 IN A 192.33.4.12
d.root-servers.net. 78383 IN A 199.7.91.13
e.root-servers.net. 518309 IN A 192.203.230.10
f.root-servers.net. 78358 IN A 192.5.5.241
g.root-servers.net. 78365 IN A 192.112.36.4
h.root-servers.net. 78365 IN A 198.97.190.53
i.root-servers.net. 78476 IN A 192.36.148.17
j.root-servers.net. 431905 IN A 192.58.128.30
k.root-servers.net. 431911 IN A 193.0.14.129
l.root-servers.net. 78731 IN A 199.7.83.42
m.root-servers.net. 79004 IN A 202.12.27.33
a.root-servers.net. 518309 IN AAAA 2001:503:ba3e::2:30
b.root-servers.net. 518309 IN AAAA 2001:500:200::b
c.root-servers.net. 518309 IN AAAA 2001:500:2::c
d.root-servers.net. 518309 IN AAAA 2001:500:2d::d
e.root-servers.net. 518309 IN AAAA 2001:500:a8::e
f.root-servers.net. 518309 IN AAAA 2001:500:2f::f
g.root-servers.net. 518309 IN AAAA 2001:500:12::d0d
h.root-servers.net. 518309 IN AAAA 2001:500:1::53
i.root-servers.net. 518309 IN AAAA 2001:7fe::53
j.root-servers.net. 518309 IN AAAA 2001:503:c27::2:30
k.root-servers.net. 518309 IN AAAA 2001:7fd::1
l.root-servers.net. 518309 IN AAAA 2001:500:9f::42
m.root-servers.net. 518309 IN AAAA 2001:dc3::35

...
...

这里放大的原因嘛,主要在于 ADDITIONAL SECTION,这里面能附带很多信息。而像 8.8.8.8 这种著名的 localDNS,一般都去掉了ADDITIONAL SECTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
» dig @x.x.x.x . ns
...
...

;; QUESTION SECTION:
;. IN NS

;; ANSWER SECTION:
. 86774 IN NS m.root-servers.net.
. 86774 IN NS b.root-servers.net.
. 86774 IN NS c.root-servers.net.
. 86774 IN NS d.root-servers.net.
. 86774 IN NS e.root-servers.net.
. 86774 IN NS f.root-servers.net.
. 86774 IN NS g.root-servers.net.
. 86774 IN NS h.root-servers.net.
. 86774 IN NS i.root-servers.net.
. 86774 IN NS a.root-servers.net.
. 86774 IN NS j.root-servers.net.
. 86774 IN NS k.root-servers.net.
. 86774 IN NS l.root-servers.net.

;; Query time: 20 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Thu Sep 24 18:48:05 CST 2020
;; MSG SIZE rcvd: 239

不过就算禁用了 ADDITIONAL SECTION,还有些情况是会直接在 ANSWER SECTION 返回大量内容的,nsA 等可能没有多少,但是 RRSIG 可就多咯:

1
2
3
4
5
6
7
8
9
10
11
12
13
# macr0phag3 in ~ [19:02:57]
» dig @8.8.8.8 defcon.org RRSIG
...
...

;; QUESTION SECTION:
;defcon.org. IN RRSIG

;; ANSWER SECTION:
defcon.org. 0 IN RRSIG NSEC3PARAM 10 2 0 20201021013759 20200921011007 50153 defcon.org. GtoW4gli0iuyaTG75sWltQJ3xfXs08YWr8wG/tEd9IDqyOxHYUoJrSnj TiDyPItyoUECBZPW1aWDgFdkqDUxqFMjwwl4wjmVjX4gjvHoWJ6X2lrV kHVK4FQGN+uuCyx/OPjH6B8VqxeHkFqT1+JM3BRhbgwAAso+/d9DyJqF NYR5LvhLl6laAsTnTJlCndMTIUouHwpxEmYZ6BC+20Jr7xBypE4lzQYF DM6s7A9Cpy4HInwFpl9NjjS7OCku0RZYpbRXvOATQiv0VuHyMRFdbK9S Bkn+MEjYaUhl+0x+H4Ek+gEDmRk5wduCTxscyqaXzoHtJnzw510ztZWw Rk/wtTr8xSHmQxzM7ndw9yomE/3VOPCmY2atuCo8k5a+ugBzQS+RraXD dz0tWLU8fBYnv3tr04Peq/RAyi4r3Yek5J0Jz6Jy2u+Ig5oGe16XJ0A4 rh94UEM+0N6G/JS6P5EvuG9gfHNFxAOVcrZRYpwGXBW63dUrEc3oX6xh 1z7etZb6F/uNuxIYCyiZxmX/BgGYXM2J/1YO3vLhehmAhfbjTJh8MmKZ yWvs9H0LQAuZrGjrSQKzIuGAgpot5X58lERsyuNNZqB8vXkDuGessFhP oHXbhADjBGcsdq/tyKRlq08+st0cK5ZijExdgobZpkCFsLEaOnzDu1qq nuGHQriZjXw=

...
...

这还是做了限制的,如果你找个没做限制的 localDNS 或者是权威 DNS 服务器,返回内容可就大了,怎么也得有个 20 倍吧。甚至你还可以用 dig @目标ip defcon.org any,所有类型的记录都返回,更上一层楼。由于 any 实在是太 imba 了,各大 localDNS 一般都会限制 any 的查询,就算不限制,一般也会无视 bufsize 转为 TCP 传输,这样就没法伪造源 ip 了,至少自己不会成为 DDoS 放大的工具人(虽然还是会消耗自己的流量与性能)。

上面的倍数都是 1:n,如果攻击者手里有很多肉鸡的话,那画面就更美了。

不过我感觉 localDNS 一般不会遭受 DDoS,攻击者一般都会用 localDNS 来放大流量打别人。除非这个 localDNS 本身非常有价值,例如大运营商的 localDNS 或者是著名的公共 localDNS,能 D 成功的话,影响范围非常大。但是这些很有价值的 localDNS 一般都会有很好的防护,so...而权威服务器一般就是重灾区了,一旦成功影响面广,所以会面对各种放大型 DDoS 协议的攻击。

至于防护嘛,同样留到 DDoS 系列再讲好了

总结

这一篇终于写完了。其实还是要多做测试、实验,用 wireshark 多看看数据包。至于下一篇嘛,感觉要说的东西也很多,最近也很忙,慢慢写好了。

一份协议从提出、起草到推广,都有挺大的阻力,需要很长时间,但是不管怎么说,总是朝着更加安全的方向迈进,缓慢但坚定。


来呀快活呀


DNS 安全(二):针对 DNS 协议的攻击
https://www.tr0y.wang/2020/09/30/DNS-2-attack-dns/
作者
Tr0y
发布于
2020年9月30日
更新于
2024年5月7日
许可协议