学习Python渗透第三天:Python实现DNS请求

在互联网初,你想访问一个网站,只有访问它的IP地址,也就是一串很长的数字,但是随着互联网规模的扩大,网站的数量剧增,让人记住这么多的数字那是不现实的,现在让我记住一个六位验证码都要看好几遍,别说这么长的IP地址了。所以说为了解决这个问题,于是出现了一个新的协议:域名解析系统(Domain Name System,DNS),这个协议一出现,不但保证了互联网数据仍使用IP地址传送,而且方便用户的使用。举个例子:百度的IP是36.152.44.95,如果你想访问百度就要输入http://36.152.44.95,但是有DNS后,你输入http://www.baidu.com就可以了,你想想记拼音方便还是记数字方便。

DNS协议的工作原理和工作流程:

目前全世界域名上亿个,所以DNS服务器肯定不止一台,而是由很多台组成的一个DNS服务器群,既然是一个群体,就肯定有分工才能让这个群体有序工作,所以域名也分为通用顶级域名(gTLD)和国家地区顶级域名(ccTLD),其中com,net这种3个字母的域名一般就是通用顶级域名,而cn,jp这种两个字母的一般就是国家地区顶级域名。举个例子:www.baidu.com,我们从右往左看,com是通用顶级域名,它的下一级就是baidu,是顶级域名下的一个次级域名,而www就是baidu下的次级域名,所以我们一般渗透时收集信息说的找某个网站的子域名,就是找最左边的那个域名的其他可以登录的。比如我们都知道www.baidu.com是百度的主站,而有可能zhidao.baidu.com就是百度的一个子站。

那我们如果在自己的电脑上想访问www.baidu.com,DNS是怎样工作的呢?当你请求这个地址的时候,会首先向本地的DNS服务器进行请求,如果本地的缓存有这个IP,将会返回,如果没有,它就要开始走流程了:

1,查找根域名服务器地址,然后向根域名服务器发送请求,根域名服务器会分析这个域名www.baidu.com,分析出它的根域名是com,并返回说你去找com域名服务器。

2,得到返回后知道要去找com域名服务器,于是发送请求,com域名服务器继续分析www.baidu.com这个域名。分析出com的下一级是baidu,并返回说你去找baidu域名服务器

3,得到返回后发送请求到baidu.com域名服务器,baidu.com域名服务器分析得到www.baidu.com的IP地址并返回,于是就得到了www.baidu.com的IP地址了

以上就是DNS的工作流程。

DNS数据包结构:

我们要模拟DNS的发送,那肯定少不了了解DNS数据包的内容结构,DNS数据包分成头部和正文两部分,而头部比较重要的两个字段包括Transaction ID和Flags,其中Transaction ID是一个十六位的标识,会包含在客户端的请求包中,然后当服务器响应后也会将这个标识包含在响应包中,这样客户端在接收的时候找这个标识就行,能防止混淆。

而Flags是DNS的标志位,注意,Transaction ID是标识,这个是标志。Flags一共包含七个值:

QR:查询/响应标志,0为查询,1为响应

opcode:0标识标准查询,1标识反向查询,2标识服务器请求状态

AA:指出应答的服务器是查询域名的授权解析服务器

TC:用来指出数据包比语序的长度还要长,导致被截断

RD:建议域名服务器进行递归解析

RA:表示服务器是否支持递归查询

rcode:返回码,0表示没有差错,2表示服务器错误等

以上就是头部重要的内容,接下来是正文重要的字段主要是Queries和Answers的内容,Queries区域的内容有:

Name:表示要查询的域名

Tpye:该字段最常见的取值为1,表示由域名获得IPV4地址

Class:该字段的取值总是IN,表示互联网信息。

使用Scapy模拟DNS的请求:

1,首先我们查看DNS的结构:

from scapy.all import DNS,ls

ls(DNS)

这里我们可以看出,内部结构与我们上面介绍的字段一一对应,从id到rcode是DNS数据包的头部,而qd对应的是Queries,但是我们上面介绍的Queries有三个部分,这里我们可以利用ls(DNSQR)来进行查看后,知道结构是怎样的,再进行赋值。

from scapy.all import DNSQR,ls

ls(DNSQR)

2,知道结构后,我们利用scapy构造DNS请求数据包,这个数据包分成三个协议,分别是IP,UDP,DNS,在IP部分要指明目标IP地址(也就是本机DNS服务器的IP地址),怎样知道本机DNS服务器的IP地址呢,windows可以使用ipconfig /all进行查看

3,然后使用以下语句构造IP协议:

IP(dst="DNS的地址")

4,在UDP中,由于DNS服务器使用的是53号端口,因此使用以下语句构造UDP协议:

UDP(dport=53)

5,DNS是最核心的部分,这里需要设置的东西很多,分别有会话标识(id),查询/响应标志(qr),opcode,递归解释标识,以及Queries中的qname部分,需要注意的是,其他字段可以直接赋值,但是Queries中的部分需要使用DNSQR来进行赋值,因为DNS包中没有这一部分,上面我们提到过。下面开始写代码。

DNS(id=166,qr=0,opcode=0,rd=1,qd=DNSQR(qname="www.baidu.com"))
#这里标识为166,用于标识数据包,可以随意设置
#qr=0标识查询,qr=1表示响应,因为我们是查询域名的IP,所以用0
#opcode=0表示标准查询
#rd=1表示递归查询
#qd=DNSQR(qname="www.baidu.com")表示要查询的问题,也就是要查询的域名

构造好后,我们用sr1()来发送数据,并用dns_pkt来接收,这里使用sr1()来发送,不用sr(),是因为sr1()只接收返回的第一个数据包,而sr()会接收返回的全部数据包并返回一个列表,这里我们用不到,所以就用sr1()。

dns_pkt=sr1(pkt)

完整代码如下:

from scapy.all import IP,DNS,DNSQR,UDP,sr1,ls
ip_DNS=IP(dst="192.168.87.224")
udp_DNS=UDP(dport=53)
dns_DNS=DNS(id=166,qr=0,opcode=0,rd=1,qd=DNSQR(qname="www.baidu.com"))
pkt=udp_DNS/ip_DNS/dns_DNS
dns_pkt=sr1(pkt)
ls(dns_pkt)

当发出数据包之后,DNS服务器应答的数据包会将请求域名的IP地址放在an字段中,但是需要注意的是有时一个域名可能会对应多个IP地址,此时需要使用['an'][n]来进行区分,第一个记录是['an'][1],其中每个记录又包含rname,type,rclass,ttl,tdlen和rdata字段,这里的rdata字段保存的就是返回的IP地址,所以我们想要获得返回的IP地址就需要这样写:

dns_result_IP = dns_pkt[DNS].an[1].rdata
#这里使用an[1]而不是an[0]是因为IP地址存放在an[1],an[0]可能存放的是请求的域名

考虑到返回的记录可能有多个,所以此处需要使用循环完成,优化后的代码是这样的:

rom scapy.all import IP,DNS,DNSQR,UDP,sr1,ls
ip_DNS=IP(dst="DNS服务器地址")
udp_DNS=UDP(dport=53)
dns_DNS=DNS(id=166,qr=0,opcode=0,rd=1,qd=DNSQR(qname="www.baidu.com"))
pkt=udp_DNS/ip_DNS/dns_DNS
dns_pkt=sr1(pkt)
count=1
while True:
    try:
        if dns_pkt[DNS].an[count].type==1:
            #这串代码的意思是判断第count个资源类型是否是=1,就是资源类型是否是IP类型
            dns_result_IP = dns_pkt[DNS].an[count].rdata
            print(dns_result_IP)
    except IndexError:
        break

黑客是如何利用DNS协议进行攻击的

我们知道怎样构造DNS数据包后,也要清楚这样一个协议,黑客是怎样想到利用他进行攻击的呢?

1,DNS请求泛洪攻击

DNS泛洪攻击就是通过大量的DNS请求,导致DNS服务器无法响应,就比如说你开了一个快递点,本来是很有序的客户来说取件号,你帮他取,但是突然来了一群人,不排队,每个人都在说自己的取件号,让你快点帮自己取件,这时候就忙不过来了。

2,DNS放大攻击

这次不是攻击服务器,而是利用DNS服务器的放大效应来攻击其他设备,比如你向DNS服务器发送的请求数据包时60B大小,然后服务器返回的数据包是300B,现在来看这些数据包大小算是小菜一碟,但是如果攻击者伪造大量的IP地址向服务器进行请求,网络上大量的DNS服务器,会响应请求,然后就会返回大量的相应包,几百B就会变成几千GB,这样电脑就直接被“撑爆”了。

3,DNS欺骗

DNS欺骗主要是攻击在内网的用户,当受害者需要访问某个外部网站时,设备会向外部发送DNS请求,攻击者只要截获到这个请求,并伪造DNS应答数据包,然后就能实现DNS欺骗

怎样更简单的利用Python构造DNS数据包

Scapy是一个相对底层的模块,如果你想要更简单的进行各种DNS的相关操作,则可以选择dnspython之类的相关高级模块,这个模块中最常用的是resolver类的query方法,这个方法的完整格式如下:

query(self,qname,rdtype=1,rdclass=1,tcp=False,sourse=None,raise_on_no_answer=True,source_port=0)

其中常用的参数含义如下:

qname:表示要查询的域名

rdtype:表示解析类型,默认为1,通常代表A记录(IPV4地址记录),其他还有MX记录和CNAME记录

rdclass:表示网络类型,默认为1,通常表示IN类型(Internet),其他还有CH类型和HS类型

tcp:表示查询是否使用TCP

source:表示源IP地址,即发送请求的IP地址

raise_on_no_answer:这是一个布尔值参数,用于指示是否在没有收到回答时引发异常,默认为True

source_port:表示源端口号

下面来代码操作一下:

from dns import resolver
ans = resolver.query("www.baidu.com",'A')
#查询的结果保存在ans中,ans的格式与我们之前说的DNS相似,也包含rdtype,answer等字段,此次查询结果都保存在ans.response.answer中,因为应答中可能包含多个结果,所以利用循环进行输出
for i in ans.response.answer:
    print(i)

果然很快就得到了结果

今天的学习分享就到这里了,如果有什么不对的地方,还请大家的多多指正,谢谢大家的观看。

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值