网络攻防技术——DNS攻击

发布时间 2023-12-28 15:18:53作者: Leo1017

实验11:TCP攻击实验

实验内容:

本实验的目标是让学生获得对DNS(域名系统)的各种攻击的第一手经验。DNS是互联网的电话簿;它将主机名转换为IP地址,反之亦然。这种转换是通过DNS解析实现的,这种解析发生在幕后。DNS欺骗攻击以各种方式操纵此解析过程,目的是将用户误导到其他目的地,这些目的地通常是恶意的。本实验室主要研究几种DNS欺骗攻击技术。学生将首先设置和配置DNS服务器,然后在实验室环境中的目标上尝试各种DNS欺骗攻击。

 

第一个大实验任务(本地DNS欺骗)中进行的攻击假设攻击者位于同一本地网络上,因此可以嗅探DNS数据包。这个假设是为了简化实验任务。第二个大实验任务为远程DNS攻击实验,攻击者在没有嗅探数据包的情况下发起远程欺骗攻击,远程攻击实验室比本地DNS欺骗实验更具挑战性。

 

本地DNS攻击

启动docker容器

本实验的网络拓扑结构

本实验做了一些配置,以使实验中的攻击可以生效

  1. DNS服务器现在在其DNS查询中随机化源端口号,配置源端口固定为33333
  2. 关闭DNSSEC:DNSSEC通过使用公钥加密和数字签名技术来实现其目标。每个域名都有一个与之关联的公钥,该公钥用于对 DNS 数据进行签名。当客户端向 DNS 服务器发送查询时,服务器会返回签名过的响应。客户端使用域名的公钥来验证响应的签名,并确保数据的完整性和真实性
  3. 当DNS服务器收到针对 "attacker32.com"域的查询时,它会将查询转发给指定的转发器(forwarders),在这里是攻击者的DNS服务器(ns.attacker32.com),而不是直接回答查询,相当于受害者访问恶意域名可以被我们定向到任何恶意网站

进入用户容器,测试DNS

DNS配置正常

 

 

首先刷新用户本地DNS服务器的缓存,否则本地DNS服务器回复地很快,我们伪造响应的程序竞争不过

一个典型的DNS数据包可以包含以下字段

Header(头部):包含标识和控制信息,如查询类型(标准查询、反向查询等)、回答标志等。

Question(问题部分):包含一个或多个问题项,每个项包括查询的域名和查询类型(比如 A 记录、MX 记录等)。

Authority(权威部分):当服务器本身无法解析时,会返回对该域名的权威服务器的记录。

Additional(附加部分):包含了一些额外的信息,比如权威服务器的 IP 地址等。

参考实验手册给出的代码框架,DNS服务运行在UDP协议的53号端口上,作为过滤器嗅探DNS数据包,重要的是DNS数据包部分的构造,各字段的解释如下:

id:交易id;应与请求中的相同。

qd:查询域;应与请求中的相同。

aa:权威答案(1表示答案中包含权威答案)。

rd:Recursion Desired(0表示禁用递归查询)。

qr:查询响应位(1表示响应)。

qdcount:要查询的域的数量

ancount:回答部分中的记录数

nscount:权威部分的记录数

arcount:附加部分中的记录数

这里只需要有问题部分即可,修改返回的IP地址为6.6.6.6,type字段是A,表示是域名到IP解析的DNS记录类型

运行该文件    

在用户机上使用dig命令查询example.com的IP地址,发现首先收到的数据包是我们的攻击程序发出的数据包,返回的IP地址为我们设置的6.6.6.6,攻击成功

实验手册还给出了一种延迟向网段外部的DNS服务器进行查询的方法,以提高攻击的成功率

 

首先刷新用户本地DNS服务器的缓存,这样本地DNS服务器会请求远程DNS服务器

之前是攻击用户,现在改成攻击本地DNS服务器,即把本地DNS服务器上的记录修改成恶意IP,于是过滤IP地址,捕捉本地DNS服务器发送给远程DNS服务器的数据包,各字段不变,为了验证实验效果,将IP地址换成7.7.7.7,完整代码如下:

在攻击机上运行攻击程序

在用户机上使用dig命令查询example.com的IP地址,发现首先收到的数据包是我们的攻击程序发出的数据包,返回的IP地址为我们设置的7.7.7.7,攻击成功

 

首先刷新用户本地DNS服务器的缓存

增加DNS数据包中的权威部分,返回查询域名的权威DNS服务器,将这个权威服务器的地址修改成攻击者的DNS服务器,攻击者就可以自由决定用户对example.com域名的访问指向哪台服务器,比如攻击者的恶意网站

Type字段是NS,用于指示域名的权威 DNS 服务器,对应在DNS数据包构造中加入这些字段,修改IP地址为8.8.8.8,完整代码如下:

在攻击机上运行攻击程序

在用户机上使用dig命令查询example.com的IP地址,发现首先收到的数据包是我们的攻击程序发出的数据包,返回的IP地址为我们设置的8.8.8.8,攻击成功,同时返回的还有我们设置的权威字段,是example.com的权威DNS服务器地址

在用户的本地DNS服务器上查询example.com的DNS缓存记录如下,发现增加了攻击者DNS服务器对example.com域名的子域名的一些记录,其中email.example.com子域名的IP地址是1.2.3.6

在用户容器中查询email.example.com的IP地址,返回的正是上面查到的1.2.3.6,说明是由攻击者DNS服务器解析的

刷新DNS缓存后重新查询email.example.com的IP地址,正常由用户DNS服务器解析的记录如下,发现明显不同

 

首先刷新用户本地DNS服务器的缓存

在权威部分增加google.com的权威DNS服务器地址

在攻击机上运行攻击程序

在用户机上使用dig命令查询example.com的IP地址,发现首先收到的数据包是我们的攻击程序发出的数据包,返回的IP地址为我们设置的8.8.8.8,证明攻击程序发出的响应包被成功接受

使用dig命令查找google.com的域名,发现无法解析,没有返回IP地址,这是因为google.com的权威DNS服务器被设置成攻击者的DNS服务器,而攻击者的DNS服务器上没有google.com的DNS记录,所以没有返回IP地址

这时查看用户本地DNS服务器的DNS缓存记录,发现设置的8.8.8.8的DNS记录被成功缓存,google.com的权威DNS服务器也被设置成了攻击者的DNS服务器

首先刷新用户本地DNS服务器的缓存

根据实验手册的要求,补充完整DNS数据包的回答、权威和额外部分

运行攻击程序

在用户机上使用dig命令查询到的example.com的IP地址是攻击者的DNS服务器提供的IP地址(1.2.3.5),并不是我们填充的10.10.10.10,这是因为在拿到example.com的权威DNS服务器后,向权威DNS服务器发起了查询请求,第一条是ns.example.com,但这个DNS服务器不存在,就继续访问第二条攻击者的DNS服务器,拿到了1.2.3.5的IP地址

但是当我使用dig example.com(不加www)查询时,返回的结果是我们构造的IP地址,ns.attacker32.com的IP地址也变成了我们构造的IP地址,这是由于`www.example.com`是`example.com`的一个子域名,还可以有其他的域名前缀,比如ftp等,对不同域名的查询结果当然不同,个人猜测是因为子域名的范围更小,本地DNS服务器认为远程DNS服务器并没有子域名的记录,只有父域名的记录,所以根据权威部分自己又去查了一遍

- 攻击用户主机时,用户主机收到的就是我构造的DNS响应,只不过具体采纳响应中的哪些部分取决于主机的策略

- 攻击本地DNS服务器时,我构造的DNS响应只被本地服务器收到,本地DNS服务器根据我构造的响应自己还会去查一次,自己查到的内容才会发给用户主机

具体情况如下:

查看用户本地DNS服务器的DNS缓存记录,首先发现构造的DNS响应包中的权威部分的内容成功写入缓存,两个DNS服务器都是example.com的权威DNS服务器

但是附加部分的内容都没有写入DNS缓存中,因为ns.attacker32.com在本地DNS服务器中原本就有设置(见环境配置dns配置与测试部署部分),所以并没有被我们构造的额外部分影响

Facebook.com和example.net都查不到记录

这是因为额外部分提供的域名IP映射对在权威部分都没有提及,额外部分提供的IP地址通常是对权威部分的补充,如果权威部分都没有,那么这些记录就会被丢弃,而不会写入缓存中

远程DNS攻击

实验准备部分和本地DNS攻击相同,这里不再赘述

(这部分主要是对kaminsky攻击的介绍,没有具体的实验)

Kaminsky 攻击的原理:发送多个不存在的域名请求,此时 DNS 服务器会向其权威服务器发起请求,此时攻击者发送大量伪造的DNS回应,并猜测其transaction ID,在权威服务器回应之前到达,且某一个猜对了 transactionID 的话,就能成功写入缓存

Qdsec = DNSQR(qname='fake.example.com') 表示创建一个DNS查询记录,其中 qname 指定了查询的域名为 'fake.example.com'

dns = DNS(id=0xABCD, qr=0, qdcount=1, qd=Qdsec) 表示创建一个DNS消息,qd 字段指定了查询记录对象(即上面创建的 Qdsec 对象),将事务id设置为0xABCD

请求的域名设置成不存在的域名,这样本地DNS服务器就一定会请求子网外的DNS服务器

在攻击机上运行程序

使用wireshark抓包,成功捕捉到了攻击程序发出的DNS请求数据包,查看事务ID,发现是我们设置的0xabcd,证明是我们发出的DNS请求数据包

同时,本地DNS服务器向子网外的DNS服务器发出来查询请求,证明我们的伪造请求成功被接受

查看DNS数据包如下,对fake.example域名进行查询

源IP地址在实际攻击中应该换成真实的权威DNS服务器地址,目标端口号在配置中已经固定为33333号端口,这里将返回的权威字段中example.com的权威DNS服务器设置成攻击者的DNS服务器地址,之后地址解析就会请求攻击者的DNS服务器,同样查询不存在的域名

运行该程序

使用wireshark抓包分析,抓到数据包,并且事务ID是我们设置的

可以看到我们的响应数据包成功到达本地DNS服务器

使用hexdump查看生成的请求数据包,发现查询域名(.fake)在数据包中的偏移值是41

查看生成的响应数据包,需要修改两处随机域名,分别是偏移值41和64,同时还要修改序列事务id,偏移值是28

完整代码如下:

每个域名发送500×2=1000个数据包,id发送到65535停止程序即可

在攻击机上运行我们的程序,程序遍历65535个可能的事务id列表,并发出DNS请求和响应数据包,这里可能一次不成功,可以多运行几次,在运行几次后,攻击成功

登录本地DNS服务器,并查看当前的缓存记录,发现成功将example.com的权威DNS服务器修改成了攻击者的DNS服务器(ns.attacker32.com)

使用wireshark查看程序运行的最后面的本地DNS服务器查询记录,对example.com下域名的请求都发往了攻击者的DNS服务器,也能证明攻击成功

进入用户容器,启动wireshark后使用dig命令对example.com进行DNS查询,发现返回的IP地址是攻击者DNS服务器提供的IP地址(1.2.3.5)

使用wireshark抓包,发现用户容器发出的DNS查询请求都是发向本地DNS服务器后,本地DNS服务器又马上向攻击者DNS服务器(10.9.0.153)发出DNS查询请求,证明攻击成功

清除服务器的DNS缓存后重新攻击,在攻击成功后执行第二条命令,发现和第一条命令的执行结果相同,返回的IP地址都是攻击者DNS服务器提供的IP地址(1.2.3.5)

使用wireshark抓包的结果如下,由于指定了DNS服务器,用户机先访问用户本地DNS服务器,拿到攻击者DNS服务器的地址,然后直接向攻击者的DNS服务器发送DNS查询请求

 

总结

DNS缓存攻击:由于DNS采用UDP协议传输查询和应答数据包,属于简单信任机制。对接收到的应答数据包仅进行原查询包IP 地址、端口和随机查询ID 的确认,而不会对数据包的合法性做任何分析。如果若匹配,则接受其作为正确应答数据包,继续DNS 解析过程,并丢弃后续到达的所有应答数据包。这就使得攻击者可以仿冒权威名字服务器向缓存DNS 服务器发送伪造应答包,力争抢先完成应答以污染DNS 缓存。

如果攻击者发送的伪造应答包在权威DNS发送的正确应答包之前到达缓存DNS 服务器,并与原查询包IP 地址、端口和随机查询ID 相匹配,就能够成功污染DNS 缓存。

如何防御:

1. 源端口随机化:DNS服务器每次通信都会在1024到65536号端口中随机选择一个端口号和对方进行通信连接,导致攻击所需的时间加长,理论上不可能赶在真消息到达之前"加塞"

2. 0x20编码:即随机化大小写验证技术,该技术会匹配请求包和响应包的大小写,如果大小写不匹配就会丢弃响应包,比如对于长度为8个字符串的域名,就会产生2-8个不同的字符串

3.多个权威DNS:作为权威域名的负责方,要尽量的部署多台权威DNS,比如一主多备。这样能有效的防止域名被投毒。

4. DNSSEC协议:DNSSEC是一种新的DNS协议,可对DNS请求进行加密以防止伪造。该协议尚未得到广泛采用,因为它确实会减慢DNS进程。HTTPS上的DNS(DoH)是下一版本DNS的竞争规范,可以在不牺牲速度的情况下确保DNS请求的安全。